/// <summary> /// Call a contract /// </summary> /// <param name="call">The inputs for the contract call</param> /// <returns></returns> public async Task <Dictionary <int, BeContractReturn> > CallAsync(BeContractCall call) { if (call == null) { throw new BeContractException("Contract call is null"); } var contract = await BcService.FindBeContractByIdAsync(call.Id); Console.WriteLine($"Calling contract {contract?.Id}"); //Filter to only give the correct outputs var notFiltredReturns = await CallAndLoopQueriesAsync(call, contract); var filtredReturns = new Dictionary <int, BeContractReturn>(); var groupedOutputs = contract.Outputs?.GroupBy(output => output.LookupInputId); groupedOutputs.ToList().ForEach(group => { var beContractReturn = new BeContractReturn { Outputs = new Dictionary <string, dynamic>() }; group.ToList().ForEach(output => { var ret = notFiltredReturns[output.LookupInputId].Outputs.FirstOrDefault(o => o.Key.Equals(output.Key)); beContractReturn.Id = notFiltredReturns[output.LookupInputId].Id; beContractReturn.Outputs.Add(ret.Key, ret.Value); }); filtredReturns.Add(group.Key, beContractReturn); }); filtredReturns.ToList().ForEach(ret => { Console.WriteLine($"At LookupInputId {ret.Key} for contract {ret.Value.Id}"); ret.Value.Outputs.ToList().ForEach(output => { Console.WriteLine($"\t{output.Key} - {output.Value}"); }); }); return(filtredReturns); }
/// <summary> /// Find the contract with the call id /// Loop over every query /// </summary> /// <param name="call">The inputs for the contract call</param> /// <returns>Return a list of contract id with his return types</returns> private async Task <List <BeContractReturn> > CallAndLoopQueriesAsync(BeContractCall call, BeContract contract = null) { if (contract == null) { contract = await BcService.FindBeContractByIdAsync(call.Id); } if (contract == null) { throw new BeContractException($"No contract was found with id {call.Id}"); } validators.ValidateBeContractCall(contract, call); var returns = new List <BeContractReturn>(); //If it's a nested contract, loop through it if (contract?.Queries?.Count > 0) { foreach (var q in contract.Queries) { //Create the BeContractCall var callInQuery = new BeContractCall() { Id = q.Contract.Id, ISName = call.ISName, Inputs = new Dictionary <string, dynamic>() }; //Fill in the inputs of the BeContractCall q.Contract.Inputs?.ForEach(input => { var mapping = q.Mappings.FirstOrDefault(m => m.InputKey.Equals(input.Key)); if (mapping == null) { throw new BeContractException($"No mapping exists for inputKey {input.Key}"); } //We need to check our contract input if (mapping.LookupInputId == 0) { if (!call.Inputs.TryGetValue(mapping.LookupInputKey, out dynamic value)) { throw new BeContractException($"No value was found for the key {mapping.LookupInputKey} in the lookupinputid n°{mapping.LookupInputId}") { BeContractCall = call } } ; callInQuery.Inputs.Add(input.Key, value); } //Find the contract where we need to search the value else { if ((mapping.LookupInputId - 1) >= returns.Count) { throw new BeContractException($"Mapping LookupInputId n°{mapping.LookupInputId} is bigger then the returns size {returns.Count}"); } var returnToBeUsed = returns[mapping.LookupInputId - 1]; if (returnToBeUsed == null) { throw new BeContractException($"No output was found for query {q.Contract.Id} with mapping lookupinputid n°{mapping.LookupInputId}") { BeContractCall = call } } ; //We need to check our contract outputs if (!returnToBeUsed.Outputs.TryGetValue(mapping.LookupInputKey, out dynamic value)) { throw new BeContractException($"No value was found for the key {mapping.LookupInputKey} in the contract outputs of n°{mapping.LookupInputId}") { BeContractCall = call } } ; callInQuery.Inputs.Add(input.Key, value); } }); //Call the contract var loopdQueries = await CallAndLoopQueriesAsync(callInQuery); if (loopdQueries.Contains(null)) { throw new BeContractException($"Got an null in loopqueries with id {callInQuery.Id}"); } returns.AddRange(loopdQueries); } ; } else { var serviceReturns = await CallServiceAsync(contract, call); if (serviceReturns == null) { throw new BeContractException($"Got an null in serviceCall with id {call.Id}"); } returns.Add(serviceReturns); } return(returns); }