/// <summary> /// /// This method will allow you to extend the functionality of the parser for Wonka's markup language. /// By default, there is a common set of operators that can be used in the Wonka markup for certain /// Rule types (like "ASSIGN_SUM" will trigger the creation of an Arithmetic rule). By adding a /// custom operator, the user can extend the language of Wonka's markup language, where an operator name /// can now lead to the remote execution of code elsewhere (Web method, Ethereum contract method, etc.). /// So, for example, there could be a new operator used in a markup file: /// /// <validate err="severe"> /// <criteria op="AND" > /// <eval>(N.PrimaryValue) GET_ETH_METHOD_VALUE('SomeValue')</eval> /// </criteria> /// </validate> /// /// Where the operator 'CALL_ETH_METHOD' is defined before parsing through the use of this method. /// When parsing the markup, the parser will know how to create and add an instance of CustomOperatorRule /// to the RuleTree, one which knows how to execute the right codepath defined by 'GET_ETH_METHOD_VALUE'. /// When executing, the rule of GET_ETH_METHOD_VALUE will be be invoked and its result /// will be assigned to 'N.PrimaryValue'. /// /// NOTE: That says "po-Op-Source", but if you want to look at it as "poOp-Source", well, that's up to you, /// and try not to laugh yourself silly /// /// <param name="psCustomOpName">The name of the new custom operator</param> /// <param name="poOpSource">The data that defines how to execute this new custom operator</param> /// <returns>None</returns> /// </summary> public void AddCustomOperator(string psCustomOpName, WonkaBizSource poOpSource = null) { if (this.BasicOps.Contains(psCustomOpName)) { throw new Exception("ERROR! Provided operator is already a basic operator within the rules engine."); } if (this.ArithmeticLimitOps.Contains(psCustomOpName)) { throw new Exception("ERROR! Provided operator is already an arithmetic limit operator within the rules engine."); } if (this.DateLimitOps.Contains(psCustomOpName)) { throw new Exception("ERROR! Provided operator is already a date limit operator within the rules engine."); } if (poOpSource != null) { this.CustomOpSources[psCustomOpName] = poOpSource; } else { string sEmpty = string.Empty; this.CustomOpSources[psCustomOpName] = new WonkaBizSource(sEmpty, sEmpty, sEmpty, sEmpty, sEmpty, sEmpty, sEmpty, null); } }
public Nethereum.Contracts.Contract GetContract(WonkaBizSource TargetSource) { var web3 = GetWeb3(); var contract = web3.Eth.GetContract(TargetSource.ContractABI, TargetSource.ContractAddress); return(contract); }
public WonkaBizRulesEngine(StringBuilder psRules, Dictionary <string, WonkaBizSource> poSourceMap, Dictionary <string, WonkaBizSource> poCustomOpBlockchainSources, IMetadataRetrievable piMetadataSource = null, bool pbAddToRegistry = true) { if ((psRules == null) || (psRules.Length <= 0)) { throw new WonkaBizRuleException("ERROR! Provided rules are null or empty!"); } UsingOrchestrationMode = true; AddToRegistry = pbAddToRegistry; RefEnvHandle = Init(piMetadataSource); WonkaBizRulesXmlReader BreXmlReader = new WonkaBizRulesXmlReader(psRules, piMetadataSource, this); foreach (string sKey in poCustomOpBlockchainSources.Keys) { WonkaBizSource oTargetSource = poCustomOpBlockchainSources[sKey]; BreXmlReader.AddCustomOperator(sKey, oTargetSource); } RuleTreeRoot = BreXmlReader.ParseRuleTree(); SourceMap = poSourceMap; CustomOpMap = poCustomOpBlockchainSources; AllRuleSets = BreXmlReader.AllParsedRuleSets; this.RetrieveCurrRecord = AssembleOtherProduct; }
public static void AddNethereumERC20GetBalanceRule(this WonkaBizRuleSet poRuleSet, WonkaRefEnvironment poRefEnv, Web3 poWeb3, WonkaRefAttr poTargetAttr, string psAddRuleDesc, string psTargetOwner, string psERC20ContractAddress) { WonkaBizRule NewRule = null; WonkaBizSource DummySource = new WonkaBizSource("ERC20", psERC20ContractAddress, "", "", "", "", "", null); WonkaEthCustomOpRule CustomOpRule = new WonkaEthCustomOpRule(mnRuleCounter++, TARGET_RECORD.TRID_NEW_RECORD, poTargetAttr.AttrId, CONST_ERC20_GET_BALANCE_OP, null, DummySource); CustomOpRule.OwnerWeb3 = poWeb3; CustomOpRule.PrimaryContractAddress = psERC20ContractAddress; CustomOpRule.CustomOpDelegate = CustomOpRule.InvokeERC20GetBalance; CustomOpRule.AddDomainValue(psTargetOwner, true, TARGET_RECORD.TRID_NONE); if (!String.IsNullOrEmpty(psAddRuleDesc)) { NewRule.DescRuleId = psAddRuleDesc; } poRuleSet.AddRule(NewRule); }
public Nethereum.Contracts.Contract GetContract(WonkaBizSource TargetSource) { var account = new Account(TargetSource.Password); var web3 = new Nethereum.Web3.Web3(account); var contract = web3.Eth.GetContract(TargetSource.ContractABI, TargetSource.ContractAddress); return(contract); }
/// <summary> /// /// This method will build a trigger that will transfer tokens from a holding account to a receiver. /// /// NOTE: UNDER CONSTRUCTION /// /// </summary> public static ISuccessTrigger BuildTokenTransferTrigger(this WonkaBizSource poSource, string psRecvAddress, long pnTransferAmt, string psWeb3Url = "", System.Threading.CancellationTokenSource poTokenSrc = null) { Nethereum.Web3.Web3 web3 = WonkaExtensions.GetWeb3(poSource.Password, psWeb3Url); var TransferTrigger = new WonkaEthEIP20TransferTrigger(web3, poSource.ContractAddress, psRecvAddress, pnTransferAmt, poTokenSrc); return(TransferTrigger); }
/// <summary> /// /// This method will create a custom operator rule that will determine whether an attribute's value falls within a domain defined by the /// results of a query on a database. /// /// NOTE: UNDER CONSTRUCTION /// /// </summary> public static CustomOperatorRule BuildSqlQueryRule(this WonkaBizSource poSource, int pnRuleID, int pnTargetAttrId, string psCustomOpName, bool pbQueryDomainRule = false) { var QueryRule = new WonkaBizQueryRule(pnRuleID, pnTargetAttrId, psCustomOpName, poSource) { IsDomainQuery = pbQueryDomainRule }; return(QueryRule); }
/// <summary> /// /// This method will create a custom operator rule that will determine whether an attribute's value falls within a domain defined by the /// results of a query on a database. /// /// NOTE: UNDER CONSTRUCTION /// /// </summary> public static CustomOperatorRule BuildSqlQueryRule(this WonkaBizSource poSource, int pnRuleID, bool pbQueryDomainRule = false) { var QueryRule = new WonkaBizQueryRule(pnRuleID, poSource) { IsDomainQuery = pbQueryDomainRule }; return(QueryRule); }
public WonkaEthCustomOpRule(int pnRuleID, TARGET_RECORD peTargetRecord, int pnTargetAttrId, string psCustomOpName, WonkaBizRulesXmlReader.ExecuteCustomOperator poCustomOpDelegate, WonkaBizSource poCustomOpSource) : base(pnRuleID, peTargetRecord, pnTargetAttrId, psCustomOpName, poCustomOpDelegate, poCustomOpSource) { }
public string RetrieveValueMethod(WonkaBizSource poTargetSource, string psAttrName) { var contract = GetContract(poTargetSource); var getRecordValueFunction = contract.GetFunction(poTargetSource.MethodName); var result = getRecordValueFunction.CallAsync <string>(psAttrName).Result; return(result); }
public CustomOperatorRule(int pnRuleID, TARGET_RECORD peTargetRecord, int pnTargetAttrId, string psCustomOpName, WonkaBizRulesXmlReader.ExecuteCustomOperator poCustomOpDelegate, WonkaBizSource poCustomOpSource) : base(pnRuleID, RULE_TYPE.RT_CUSTOM_OP) { Init(peTargetRecord, pnTargetAttrId, null); CustomOpName = psCustomOpName; CustomOpDelegate = poCustomOpDelegate; CustomOpSource = poCustomOpSource; }
public string RetrieveValueMethod(WonkaBizSource poTargetSource, string psAttrName) { string sValue = ""; if (psAttrName != "VaultYieldRate") { sValue = poTargetSource.GetAttrValue(psAttrName); } // NOTE: Only useful in case of demo else { sValue = "0.12"; } return(sValue); }
public Nethereum.Contracts.Contract GetContract(WonkaBizSource TargetSource) { var account = new Account(TargetSource.Password); Nethereum.Web3.Web3 web3 = null; if ((moOrchInitData != null) && !String.IsNullOrEmpty(moOrchInitData.Web3HttpUrl)) { web3 = new Nethereum.Web3.Web3(account, moOrchInitData.Web3HttpUrl); } else { web3 = new Nethereum.Web3.Web3(account); } var contract = web3.Eth.GetContract(TargetSource.ContractABI, TargetSource.ContractAddress); return(contract); }
/// <summary> /// /// This method will return an Attribute value from a web method. /// /// <param name="poTargetSource">The Source of the Attribute's location, defined on the chain</param> /// <param name="psAttrName">The name of the Attribute which we are seeking</param> /// <returns>Contains the value of the sought Attribute</returns> /// </summary> public static async Task <string> GetAttrValueViaWebMethodAsync(this WonkaBizSource poTargetSource, string psAttrName) { using (HttpClient client = new HttpClient()) { client.DefaultRequestHeaders.Accept.Clear(); string sGetAttrVal = poTargetSource.APIWebUrl + "/" + poTargetSource.APIWebMethod + "?" + poTargetSource.APIWebParam + "=" + psAttrName; using (var responseMessage = await client.GetAsync(sGetAttrVal).ConfigureAwait(false)) { Stream receiveStream = await responseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false); StreamReader readStream = new StreamReader(receiveStream, System.Text.Encoding.UTF8); return(readStream.ReadToEnd()); } } }
/// <summary> /// /// This method will assemble the new product by iterating through each specified source /// and retrieving the data from it. /// /// <param name="poKeyValues">The keys for the product whose data we wish to extract/param> /// <returns>Contains the assembled product data that represents the current product</returns> /// </summary> public WonkaProduct AssembleCurrentProduct(Dictionary <string, string> poKeyValues) { WonkaProduct CurrentProduct = new WonkaProduct(); // NOTE: Do work here if (SourceMap != null) { foreach (string sTmpAttName in SourceMap.Keys) { WonkaBizSource TmpSource = SourceMap[sTmpAttName]; WonkaRefAttr TargetAttr = RefEnvHandle.GetAttributeByAttrName(sTmpAttName); string sTmpValue = TmpSource.RetrievalDelegate.Invoke(TmpSource, TargetAttr.AttrName); CurrentProduct.SetAttribute(TargetAttr, sTmpValue); } } return(CurrentProduct); }
private WonkaEthRulesEngine AssembleWonkaEthEngine(string psWonkaRules) { refEnvHandle = WonkaRefEnvironment.CreateInstance(false, metadataSource); string sContractAddr = ""; string sContractABI = ""; string sGetMethodName = ""; string sSetMethodName = ""; WonkaBizSource.RetrieveDataMethod retrieveMethod = null; var SourceMap = new Dictionary <string, WonkaBizSource>(); foreach (var TmpAttr in refEnvHandle.AttrCache) { var TmpSource = new WonkaBizSource(TmpAttr.AttrName, CONST_ACCT_PUBLIC_KEY, CONST_ACCT_PASSWORD, sContractAddr, sContractABI, sGetMethodName, sSetMethodName, retrieveMethod); SourceMap[TmpAttr.AttrName] = TmpSource; } WonkaEthEngineInitialization EngineInit = new WonkaEthEngineInitialization() { EthSenderAddress = CONST_ACCT_PUBLIC_KEY, EthPassword = CONST_ACCT_PASSWORD, Web3HttpUrl = CONST_TEST_INFURA_URL }; return(new WonkaEthRulesEngine(new StringBuilder(psWonkaRules), SourceMap, EngineInit, metadataSource, false)); }
public virtual void SerializeRecordToBlockchain(ICommand poCommand) { Hashtable DataValues = new Hashtable(); GetPropertiesViaReflection(poCommand, DataValues); Dictionary <string, Contract> Sources = new Dictionary <string, Contract>(); foreach (string sAttrName in moRulesEngine.SourceMap.Keys) { var contract = this.GetContract(moRulesEngine.SourceMap[sAttrName]); Sources[moRulesEngine.SourceMap[sAttrName].SourceId] = contract; } // Out of gas exception // var gas = setValueOnRecordFunction.EstimateGasAsync(sSenderAddress, "SomeAttr", "SomeValue").Result; var gas = new Nethereum.Hex.HexTypes.HexBigInteger(1000000); foreach (String sTempAttrName in DataValues.Keys) { WonkaBizSource TempSource = moRulesEngine.SourceMap[sTempAttrName]; string sSenderAddr = TempSource.SenderAddress; string sAttrValue = (string)DataValues[sTempAttrName]; var contract = Sources[TempSource.SourceId]; var setValueOnRecordFunction = contract.GetFunction(TempSource.SetterMethodName); if (!String.IsNullOrEmpty(sAttrValue)) { var receiptSetValueOnRecord = setValueOnRecordFunction.SendTransactionAsync(sSenderAddr, gas, null, sTempAttrName, sAttrValue).Result; } } }
public virtual void DeserializeRecordFromBlockchain(ICommand poCommand) { Hashtable DataValues = new Hashtable(); Dictionary <string, Contract> Sources = new Dictionary <string, Contract>(); foreach (string sAttrName in moInitData.BlockchainDataSources.Keys) { var contract = this.GetContract(moInitData.BlockchainDataSources[sAttrName]); Sources[moInitData.BlockchainDataSources[sAttrName].SourceId] = contract; } // Out of gas exception // var gas = setValueOnRecordFunction.EstimateGasAsync(sSenderAddress, "SomeAttr", "SomeValue").Result; var gas = new Nethereum.Hex.HexTypes.HexBigInteger(1000000); foreach (String sTempAttrName in moInitData.BlockchainDataSources.Keys) { WonkaBizSource TempSource = moInitData.BlockchainDataSources[sTempAttrName]; string sSenderAddr = TempSource.SenderAddress; var contract = Sources[TempSource.SourceId]; var getValueOnRecordFunction = contract.GetFunction(TempSource.MethodName); string sAttrValue = getValueOnRecordFunction.CallAsync <string>(sTempAttrName).Result; if (!String.IsNullOrEmpty(sAttrValue)) { DataValues[sTempAttrName] = sAttrValue; } } AssignPropertiesViaReflection(poCommand, DataValues); }
/// <summary> /// /// This method will assemble the new product by iterating through each specified source /// and retrieving the data directly from the third-party storage contract on the chain. /// /// <param name="poEngine">The Wonka.NET instance that represents the instance on the chain</param> /// <param name="poKeyValues">The keys for the product whose data we wish to extract (though not yet used)</param> /// <param name="psWeb3Url">The URL for the Ethereum client to which we want to connect</param> /// <returns>Contains the assembled product data that represents the current product</returns> /// </summary> public static WonkaProduct AssembleCurrentProductFromChainSources(this WonkaBizRulesEngine poEngine, Dictionary <string, string> poKeyValues, string psWeb3Url = "") { WonkaProduct CurrentProduct = new WonkaProduct(); if ((poKeyValues != null) && (poKeyValues.Count > 0)) { // NOTE: To be determined } if (poEngine.SourceMap != null) { foreach (string sTmpAttrName in poEngine.SourceMap.Keys) { WonkaBizSource TmpSource = poEngine.SourceMap[sTmpAttrName]; WonkaRefAttr TargetAttr = poEngine.RefEnvHandle.GetAttributeByAttrName(sTmpAttrName); string sTmpValue = TmpSource.GetAttrValueFromChain(sTmpAttrName, psWeb3Url); CurrentProduct.SetAttribute(TargetAttr, sTmpValue); } } return(CurrentProduct); }
/// <summary> /// /// This method will return an Attribute value using. /// /// <param name="poTargetSource">The Source of the Attribute's location, defined on the chain</param> /// <param name="psAttrName">The name of the Attribute which we are seeking</param> /// <param name="psWeb3Url">The URL for the Ethereum client to which we want to connect</param> /// <returns>Contains the value of the sought Attribute</returns> /// </summary> public static async Task <string> GetAttrValueAsync(this WonkaBizSource poTargetSource, string psAttrName, string psWeb3Url = "") { return(await poTargetSource.GetAttrValueFromChainAsync(psAttrName, psWeb3Url).ConfigureAwait(false)); }
/// <summary> /// /// This method will return an Attribute value using. /// /// <param name="poTargetSource">The Source of the Attribute's location, defined on the chain</param> /// <param name="psAttrName">The name of the Attribute which we are seeking</param> /// <param name="psWeb3Url">The URL for the Ethereum client to which we want to connect</param> /// <returns>Contains the value of the sought Attribute</returns> /// </summary> public static string GetAttrValue(this WonkaBizSource poTargetSource, string psAttrName, string psWeb3Url = "") { return(poTargetSource.GetAttrValueFromChain(psAttrName, psWeb3Url)); }
public string RetrieveValueMethod(WonkaBizSource poTargetSource, string psAttrName) { return(poTargetSource.GetAttrValue(psAttrName, CONST_ONLINE_TEST_CHAIN_URL)); }
/// <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); // The old version of deployment, pushing out a contract with all methods (i.e., library) // bool bDeploySuccess = poEngineInitData.DeployContractsClassicAsync().Result; // The new version of deployment, pushing out the contract with a link to a library bool bDeploySuccess = poEngineInitData.DeployContractsAsync().Result; if (bDeploySuccess) { 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); } else { throw new Exception("ERROR! Deployment of Wonka contracts has failed!"); } } return(bResult); }
private void ParseSingleRule(XmlNode poRuleXmlNode, WonkaBizRuleSet poTargetRuleSet) { int nNewRuleId = ++(this.RuleIdCounter); string sRuleExpression = poRuleXmlNode.InnerText; WonkaBizRule NewRule = null; if (this.CustomOpSources.Keys.Any(s => sRuleExpression.Contains(s))) { string sFoundKey = this.CustomOpSources.Keys.FirstOrDefault(s => sRuleExpression.Contains(s)); if (!String.IsNullOrEmpty(sFoundKey) && (this.CustomOpSources[sFoundKey].CustomOpRuleBuilder != null)) { WonkaBizSource CustomOpSource = this.CustomOpSources[sFoundKey]; NewRule = CustomOpSource.CustomOpRuleBuilder.Invoke(CustomOpSource, nNewRuleId); } else { NewRule = new CustomOperatorRule() { RuleId = nNewRuleId }; } } else if (this.ArithmeticLimitOps.Any(s => sRuleExpression.Contains(s))) { NewRule = new ArithmeticLimitRule() { RuleId = nNewRuleId }; } else if (this.DateLimitOps.Any(s => sRuleExpression.Contains(s))) { NewRule = new DateLimitRule() { RuleId = nNewRuleId }; } else if (sRuleExpression.Contains("NOT POPULATED")) { NewRule = new PopulatedRule() { RuleId = nNewRuleId, NotOperator = true }; } else if (sRuleExpression.Contains("POPULATED")) { NewRule = new PopulatedRule() { RuleId = nNewRuleId, NotOperator = false }; } else if (sRuleExpression.Contains("!=")) { NewRule = new DomainRule() { RuleId = nNewRuleId, NotOperator = true }; } else if (sRuleExpression.Contains("==")) { NewRule = new DomainRule() { RuleId = nNewRuleId, NotOperator = false }; } else if (sRuleExpression.Contains("NOT IN")) { NewRule = new DomainRule() { RuleId = nNewRuleId, NotOperator = true }; } else if (sRuleExpression.Contains("IN")) { NewRule = new DomainRule() { RuleId = nNewRuleId, NotOperator = false }; } else if (sRuleExpression.Contains("EXISTS AS")) { NewRule = new DomainRule() { RuleId = nNewRuleId, NotOperator = false, SearchAllDataRows = true }; } else if (sRuleExpression.Contains("DEFAULT")) { NewRule = new AssignmentRule() { RuleId = nNewRuleId, NotOperator = false, DefaultAssignment = true }; } else if (sRuleExpression.Contains("ASSIGN_SUM")) { NewRule = new ArithmeticRule() { RuleId = nNewRuleId, NotOperator = false, OpType = ARITH_OP_TYPE.AOT_SUM }; } else if (sRuleExpression.Contains("ASSIGN_DIFF")) { NewRule = new ArithmeticRule() { RuleId = nNewRuleId, NotOperator = false, OpType = ARITH_OP_TYPE.AOT_DIFF }; } else if (sRuleExpression.Contains("ASSIGN_PROD")) { NewRule = new ArithmeticRule() { RuleId = nNewRuleId, NotOperator = false, OpType = ARITH_OP_TYPE.AOT_PROD }; } else if (sRuleExpression.Contains("ASSIGN_QUOT")) { NewRule = new ArithmeticRule() { RuleId = nNewRuleId, NotOperator = false, OpType = ARITH_OP_TYPE.AOT_QUOT }; } else if (sRuleExpression.Contains("ASSIGN")) { NewRule = new AssignmentRule() { RuleId = nNewRuleId, NotOperator = false }; } if (NewRule != null) { var RuleId = poRuleXmlNode.Attributes.GetNamedItem(CONST_RULE_ID_ATTR); if (RuleId != null) { NewRule.DescRuleId = RuleId.Value; } NewRule.ParentRuleSetId = poTargetRuleSet.RuleSetId; SetTargetAttribute(NewRule, sRuleExpression); if (NewRule.RuleType != RULE_TYPE.RT_POPULATED) { SetRuleValues(NewRule, sRuleExpression); } if (RulesHostEngine != null) { NewRule.RulesHostEngine = RulesHostEngine; if (RulesHostEngine.StdOpMap != null) { if ((NewRule is ArithmeticLimitRule) && RulesHostEngine.StdOpMap.ContainsKey(STD_OP_TYPE.STD_OP_BLOCK_NUM)) { ((ArithmeticLimitRule)NewRule).BlockNumDelegate = RulesHostEngine.StdOpMap[STD_OP_TYPE.STD_OP_BLOCK_NUM]; } } } } if (NewRule != null) { poTargetRuleSet.AddRule(NewRule); } }
public WonkaBizQueryRule(int pnRuleID, int pnTargetAttrId, string psCustomOpName, WonkaBizSource poCustomOpSource, bool pbCacheDomain = false) : base(pnRuleID, TARGET_RECORD.TRID_NEW_RECORD, pnTargetAttrId, psCustomOpName, null, poCustomOpSource) { Init(pbCacheDomain); }
public WonkaBizQueryRule(int pnRuleID, WonkaBizSource poCustomOpSource, bool pbCacheDomain = false) : base(pnRuleID, TARGET_RECORD.TRID_NEW_RECORD, 0, null, null, poCustomOpSource) { Init(pbCacheDomain); }
// This constructor will be called in the case that we wish to initialize the framework // with configuration files that will be accessed through IPFS public WonkaCQSOrchTest(StringBuilder psPeerKeyId, string psRulesMarkupFile, string psRulesInitFile, string psRegistryInitFile) { moAttrSourceMap = new Dictionary <string, WonkaBizSource>(); moCustomOpMap = new Dictionary <string, WonkaBizSource>(); var TmpAssembly = Assembly.GetExecutingAssembly(); WonkaRefEnvironment RefEnv = WonkaRefEnvironment.CreateInstance(false, moMetadataSource); Wonka.IpfsW.WonkaIpfsEnvironment IpfsEnv = Wonka.IpfsW.WonkaIpfsEnvironment.CreateInstance(); // Read the XML markup that lists the business rules msRulesContents = IpfsEnv.GetFile(psPeerKeyId.ToString(), psRulesMarkupFile); // Read the configuration file that contains all the initialization details regarding the rules engine // (like addresses of contracts, senders, passwords, etc.) string sInitXml = IpfsEnv.GetFile(psPeerKeyId.ToString(), psRulesInitFile); if (!String.IsNullOrEmpty(sInitXml)) { System.Xml.Serialization.XmlSerializer WonkaEthSerializer = new System.Xml.Serialization.XmlSerializer(typeof(Wonka.Eth.Init.WonkaEthInitialization), new System.Xml.Serialization.XmlRootAttribute("Wonka.EthInitialization")); Wonka.Eth.Init.WonkaEthInitialization WonkaInit = WonkaEthSerializer.Deserialize(new System.IO.StringReader(sInitXml)) as Wonka.Eth.Init.WonkaEthInitialization; WonkaInit.RetrieveEmbeddedResources(TmpAssembly); moOrchInitData = WonkaInit.TransformIntoOrchestrationInit(moMetadataSource); System.Console.WriteLine("Number of custom operators: (" + WonkaInit.CustomOperatorList.Length + ")."); } // Read the configuration file that contains all the initialization details regarding the rules registry // (like Ruletree info, Grove info, etc.) string sInitRegistryXml = IpfsEnv.GetFile(psPeerKeyId.ToString(), psRegistryInitFile); if (!String.IsNullOrEmpty(sInitRegistryXml)) { System.Xml.Serialization.XmlSerializer WonkaEthSerializer = new System.Xml.Serialization.XmlSerializer(typeof(Wonka.Eth.Init.WonkaEthRegistryInitialization), new System.Xml.Serialization.XmlRootAttribute("Wonka.EthRegistryInitialization")); moWonkaRegistryInit = WonkaEthSerializer.Deserialize(new System.IO.StringReader(sInitRegistryXml)) as Wonka.Eth.Init.WonkaEthRegistryInitialization; moWonkaRegistryInit.RetrieveEmbeddedResources(TmpAssembly); } #region Set Class Member Variables msSenderAddress = moOrchInitData.BlockchainEngine.SenderAddress; msPassword = moOrchInitData.BlockchainEngine.Password; if (moOrchInitData.BlockchainEngine.ContractAddress == null) { msWonkaContractAddress = DeployWonkaContract(); } else { msWonkaContractAddress = moOrchInitData.BlockchainEngine.ContractAddress; } if (moOrchInitData.DefaultBlockchainDataSource.ContractAddress == null) { msOrchContractAddress = DeployOrchestrationContract(); } else { msOrchContractAddress = moOrchInitData.DefaultBlockchainDataSource.ContractAddress; } msAbiWonka = moOrchInitData.BlockchainEngine.ContractABI; msAbiOrchContract = moOrchInitData.DefaultBlockchainDataSource.ContractABI; moDefaultSource = new WonkaBizSource(moOrchInitData.DefaultBlockchainDataSource.SourceId, moOrchInitData.DefaultBlockchainDataSource.SenderAddress, moOrchInitData.DefaultBlockchainDataSource.Password, moOrchInitData.DefaultBlockchainDataSource.ContractAddress, moOrchInitData.DefaultBlockchainDataSource.ContractABI, moOrchInitData.DefaultBlockchainDataSource.MethodName, moOrchInitData.DefaultBlockchainDataSource.SetterMethodName, RetrieveValueMethod); // 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 RefEnv.AttrCache) { moAttrSourceMap[TempAttr.AttrName] = moDefaultSource; } // Here a mapping is created, where each Custom Operator points to a specific contract and its "implementation" method // - the class that contains this information (contract, accessors, etc.) is of the WonkaBreSource type moCustomOpMap = moOrchInitData.BlockchainCustomOpFunctions; #endregion Wonka.Eth.Contracts.WonkaRuleTreeRegistry WonkaRegistry = Wonka.Eth.Contracts.WonkaRuleTreeRegistry.CreateInstance(moWonkaRegistryInit.BlockchainRegistry.ContractSender, moWonkaRegistryInit.BlockchainRegistry.ContractPassword, moWonkaRegistryInit.BlockchainRegistry.ContractAddress, moWonkaRegistryInit.BlockchainRegistry.ContractABI, moWonkaRegistryInit.Web3HttpUrl); RefEnv.Serialize(moOrchInitData.BlockchainEngineOwner, msPassword, msSenderAddress, msWonkaContractAddress, msAbiWonka, moOrchInitData.Web3HttpUrl); }
public RuleTreeReport ExecuteWithReport(WonkaBizRulesEngine poRulesEngine, bool pbValidateWithinTransaction, WonkaBizSource poFlagSource) { WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance(); WonkaRefAttr CurrValueAttr = RefEnv.GetAttributeByAttrName("AccountCurrValue"); WonkaRefAttr ReviewFlagAttr = RefEnv.GetAttributeByAttrName("AuditReviewFlag"); Dictionary <string, string> PrdKeys = new Dictionary <string, string>(); var contract = GetContract(); var executeWithReportFunction = contract.GetFunction(CONST_CONTRACT_FUNCTION_EXEC_RPT); RuleTreeReport ruleTreeReport = null; if (pbValidateWithinTransaction) { var executeGetLastReportFunction = contract.GetFunction(CONST_CONTRACT_FUNCTION_GET_LAST_RPT); // NOTE: Caused exception to be thrown // var gas = executeWithReportFunction.EstimateGasAsync(msSenderAddress).Result; var gas = new Nethereum.Hex.HexTypes.HexBigInteger(1000000); WonkaProduct OrchContractCurrValues = poRulesEngine.AssembleCurrentProduct(new Dictionary <string, string>()); string sFlagBeforeOrchestrationAssignment = RetrieveValueMethod(poFlagSource, ReviewFlagAttr.AttrName); string sValueBeforeOrchestrationAssignment = RetrieveValueMethod(poFlagSource, CurrValueAttr.AttrName); var receiptAddAttribute = executeWithReportFunction.SendTransactionAsync(msSenderAddress, gas, null, msSenderAddress).Result; string sFlagAfterOrchestrationAssignment = RetrieveValueMethod(poFlagSource, ReviewFlagAttr.AttrName); string sValueAfterOrchestrationAssignment = RetrieveValueMethod(poFlagSource, CurrValueAttr.AttrName); ruleTreeReport = executeGetLastReportFunction.CallDeserializingToObjectAsync <RuleTreeReport>().Result; } else { ruleTreeReport = executeWithReportFunction.CallDeserializingToObjectAsync <RuleTreeReport>(msSenderAddress).Result; } return(ruleTreeReport); }
public void Execute(string psOrchestrationTestAddress = null, bool pbValidateWithinTransaction = false) { WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance(); Dictionary <string, WonkaBizSource> SourceMap = new Dictionary <string, WonkaBizSource>(); string sDefaultSource = "S"; string sContractSourceId = sDefaultSource; string sContractAddress = ""; string sContractAbi = ""; string sOrchGetterMethod = ""; string sOrchSetterMethod = ""; // If a 'psOrchestrationTestAddress' value has been provided, it indicates that the user wishes // to use Orchestration if (!String.IsNullOrEmpty(psOrchestrationTestAddress)) { // Here we set the values for Orchestration (like the target contract) and the implemented // methods that have the expected function signatures for getting/setting Attribute values sContractAddress = psOrchestrationTestAddress; sContractAbi = msAbiOrchTest; sOrchGetterMethod = "getAttrValueBytes32"; sOrchSetterMethod = "setAttrValueBytes32"; } else { sContractAddress = msContractAddress; sContractAbi = msAbiWonka; sOrchGetterMethod = "getValueOnRecord"; sOrchSetterMethod = ""; } // 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 moTargetAttrList) { WonkaBizSource TempSource = new WonkaBizSource(sContractSourceId, msSenderAddress, msPassword, sContractAddress, sContractAbi, sOrchGetterMethod, sOrchSetterMethod, RetrieveValueMethod); SourceMap[TempAttr.AttrName] = TempSource; } // Creating an instance of the rules engine using our rules and the metadata WonkaBizRulesEngine RulesEngine = null; if (psOrchestrationTestAddress == null) { RulesEngine = new WonkaBizRulesEngine(new StringBuilder(msRulesContents), moMetadataSource); } else { RulesEngine = new WonkaBizRulesEngine(new StringBuilder(msRulesContents), SourceMap, moMetadataSource); RulesEngine.DefaultSource = sDefaultSource; } RulesEngine.SetDefaultStdOps(msPassword); // The contract dictates that the RuleTree (and its other info, like the Source mapping) is serialized // to the blockchain before interacting with it SerializeRulesEngineToBlockchain(RulesEngine); WonkaRefAttr AccountStsAttr = RefEnv.GetAttributeByAttrName("AccountStatus"); WonkaRefAttr RvwFlagAttr = RefEnv.GetAttributeByAttrName("AuditReviewFlag"); // Gets a predefined data record that will be our analog for new data coming into the system // We are only using this record to test the .NET implementation WonkaProduct NewProduct = GetNewProduct(); string sStatusValueBefore = GetAttributeValue(NewProduct, AccountStsAttr); string sFlagValueBefore = GetAttributeValue(NewProduct, RvwFlagAttr); // SerializeProductToBlockchain(NewProduct); // Validate that the .NET implementation and the rules markup are both working properly Wonka.BizRulesEngine.Reporting.WonkaBizRuleTreeReport Report = RulesEngine.Validate(NewProduct); string sStatusValueAfter = GetAttributeValue(NewProduct, AccountStsAttr); string sFlagValueAfter = GetAttributeValue(NewProduct, RvwFlagAttr); if (Report.OverallRuleTreeResult == ERR_CD.CD_SUCCESS) { // NOTE: This should only be used for further testing // Serialize(NewProduct); } else if (Report.GetRuleSetFailureCount() > 0) { System.Console.WriteLine(".NET Engine says \"Oh heavens to Betsy! Something bad happened!\""); } else { System.Console.WriteLine(".NET Engine says \"What in the world is happening?\""); } // If a 'psOrchestrationTestAddress' value has been provided, it indicates that the user wishes // to use Orchestration if (!String.IsNullOrEmpty(psOrchestrationTestAddress)) { /** ** Now execute the rules engine on the blockchain. ** ** NOTE: Based on the value of the argument 'pbValidateWithinTransaction', we will act accordingly - ** If set to 'true', we issue a call() when we execute the rules engine, since we are only ** looking to validate here. However, if the value if 'false', we issue a sendTransaction() ** so that we can attempts to set values (i.e., change the blockchain) will take effect. ** In that case, we might want to pull back the record afterwards with a subsequent function ** call, in order to examine the record here. ** **/ var BlockchainReport = ExecuteWithReport(RulesEngine, pbValidateWithinTransaction, SourceMap[RvwFlagAttr.AttrName]); if (BlockchainReport.NumberOfRuleFailures == 0) { // Indication of a success } else if (BlockchainReport.NumberOfRuleFailures > 0) { throw new Exception("Oh heavens to Betsy! Something bad happened!"); } else { throw new Exception("Seriously, what in the world is happening?!"); } } }
// This constructor will be called in the case that we wish to initialize the framework // with configuration files locally (embedded resources, local filesystem, etc.) public WonkaCQSOrchTest() { moAttrSourceMap = new Dictionary <string, WonkaBizSource>(); moCustomOpMap = new Dictionary <string, WonkaBizSource>(); var TmpAssembly = Assembly.GetExecutingAssembly(); // Using the metadata source, we create an instance of a defined data domain WonkaRefEnvironment RefEnv = WonkaRefEnvironment.CreateInstance(false, moMetadataSource); // Read the XML markup that lists the business rules (i.e., the RuleTree) using (var RulesReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.VATCalculationExample.xml"))) { msRulesContents = RulesReader.ReadToEnd(); } // Read the configuration file that contains all the initialization details regarding the rules engine // (like addresses of contracts, senders, passwords, etc.) using (var XmlReader = new System.IO.StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.VATCalculationExample.init.xml"))) { string sInitXml = XmlReader.ReadToEnd(); // We deserialize/parse the contents of the config file System.Xml.Serialization.XmlSerializer WonkaEthSerializer = new System.Xml.Serialization.XmlSerializer(typeof(Wonka.Eth.Init.WonkaEthInitialization), new System.Xml.Serialization.XmlRootAttribute("Wonka.EthInitialization")); Wonka.Eth.Init.WonkaEthInitialization WonkaInit = WonkaEthSerializer.Deserialize(new System.IO.StringReader(sInitXml)) as Wonka.Eth.Init.WonkaEthInitialization; // Here, any embeddeded resources mentioned in the config file (instead of simple file URLs) are accessed here WonkaInit.RetrieveEmbeddedResources(TmpAssembly); // The initialization data is transformed into a structure used by the Wonka.Eth namespace moOrchInitData = WonkaInit.TransformIntoOrchestrationInit(moMetadataSource); System.Console.WriteLine("Number of custom operators: (" + WonkaInit.CustomOperatorList.Length + ")."); } // Read the configuration file that contains all the initialization details regarding the rules registry // (like Ruletree info, Grove info, etc.) - this information will allow us to add our RuleTree to the // Registry so that it can be discovered by users and so it can be added to a Grove (where it can be executed // as a member of a collection) using (var XmlReader = new System.IO.StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.WonkaRegistry.init.xml"))) { string sInitRegistryXml = XmlReader.ReadToEnd(); // We deserialize/parse the contents of the config file System.Xml.Serialization.XmlSerializer WonkaEthSerializer = new System.Xml.Serialization.XmlSerializer(typeof(Wonka.Eth.Init.WonkaEthRegistryInitialization), new System.Xml.Serialization.XmlRootAttribute("Wonka.EthRegistryInitialization")); moWonkaRegistryInit = WonkaEthSerializer.Deserialize(new System.IO.StringReader(sInitRegistryXml)) as Wonka.Eth.Init.WonkaEthRegistryInitialization; // Here, any embeddeded resources mentioned in the config file (instead of simple file URLs) are accessed here moWonkaRegistryInit.RetrieveEmbeddedResources(TmpAssembly); } // Here, we save all data from the config files to member properties // This region and the usage of member properties isn't necessary, but it's useful for debugging #region Set Class Member Variables msSenderAddress = moOrchInitData.BlockchainEngine.SenderAddress; msPassword = moOrchInitData.BlockchainEngine.Password; if (moOrchInitData.BlockchainEngine.ContractAddress == null) { msWonkaContractAddress = DeployWonkaContract(); } else { msWonkaContractAddress = moOrchInitData.BlockchainEngine.ContractAddress; } if (moOrchInitData.DefaultBlockchainDataSource.ContractAddress == null) { msOrchContractAddress = DeployOrchestrationContract(); } else { msOrchContractAddress = moOrchInitData.DefaultBlockchainDataSource.ContractAddress; } msAbiWonka = moOrchInitData.BlockchainEngine.ContractABI; msAbiOrchContract = moOrchInitData.DefaultBlockchainDataSource.ContractABI; moDefaultSource = new WonkaBizSource(moOrchInitData.DefaultBlockchainDataSource.SourceId, moOrchInitData.DefaultBlockchainDataSource.SenderAddress, moOrchInitData.DefaultBlockchainDataSource.Password, moOrchInitData.DefaultBlockchainDataSource.ContractAddress, moOrchInitData.DefaultBlockchainDataSource.ContractABI, moOrchInitData.DefaultBlockchainDataSource.MethodName, moOrchInitData.DefaultBlockchainDataSource.SetterMethodName, RetrieveValueMethod); foreach (WonkaRefAttr TempAttr in RefEnv.AttrCache) { moAttrSourceMap[TempAttr.AttrName] = moDefaultSource; } moCustomOpMap = moOrchInitData.BlockchainCustomOpFunctions; #endregion // We initialize the proxy that will be used to communicate with the Registry on the blockchain Wonka.Eth.Contracts.WonkaRuleTreeRegistry WonkaRegistry = Wonka.Eth.Contracts.WonkaRuleTreeRegistry.CreateInstance(moWonkaRegistryInit.BlockchainRegistry.ContractSender, moWonkaRegistryInit.BlockchainRegistry.ContractPassword, moWonkaRegistryInit.BlockchainRegistry.ContractAddress, moWonkaRegistryInit.BlockchainRegistry.ContractABI, moWonkaRegistryInit.Web3HttpUrl); // Here, the data domain is serialized to the blockchain for use by the RuleTree(s) RefEnv.Serialize(moOrchInitData.BlockchainEngineOwner, msPassword, msSenderAddress, msWonkaContractAddress, msAbiWonka, moOrchInitData.Web3HttpUrl); }