public T DecodeSimpleTypeOutput <T>(Parameter outputParameter, string output) { if (output == "0x") { return(default(T)); } if (outputParameter != null) { var parmeterOutput = new ParameterOutput() { DecodedType = typeof(T), Parameter = outputParameter }; var results = DecodeOutput(output, parmeterOutput); if (results.Any()) { return((T)results[0].Result); } } return(default(T)); }
public List <ParameterOutput> DecodeOutput(byte[] outputBytes, params ParameterOutput[] outputParameters) { var currentIndex = 0; // discard initial offset if (outputParameters.Count() > 1 && outputParameters.Any(oP => oP.Parameter.ABIType.Name == "tuple[]")) { // remove the starting 0x20 currentIndex = 32; } foreach (var outputParam in outputParameters) { var param = outputParam.Parameter; if (param.ABIType.IsDynamic()) { outputParam.DataIndexStart = EncoderDecoderHelpers.GetNumberOfBytes(outputBytes.Skip(currentIndex).ToArray()); // should only happen on tuples, as we look for their location if (currentIndex != 0 && (outputParam.Parameter.ABIType.Name == "tuple" || outputParam.Parameter.ABIType.Name == "tuple[]")) { outputParam.DataIndexStart = outputParam.DataIndexStart + 32; //including its current index 32 bytes } currentIndex = currentIndex + 32; } else { var bytes = outputBytes.Skip(currentIndex).Take(param.ABIType.FixedSize).ToArray(); outputParam.Result = param.ABIType.Decode(bytes, outputParam.Parameter.DecodedType); currentIndex = currentIndex + param.ABIType.FixedSize; } } ParameterOutput currentDataItem = null; foreach ( var nextDataItem in outputParameters.Where(outputParam => outputParam.Parameter.ABIType.IsDynamic())) { if (currentDataItem != null) { var bytes = outputBytes.Skip(currentDataItem.DataIndexStart).Take(nextDataItem.DataIndexStart - currentDataItem.DataIndexStart).ToArray(); currentDataItem.Result = currentDataItem.Parameter.ABIType.Decode(bytes, currentDataItem.Parameter.DecodedType); } currentDataItem = nextDataItem; } if (currentDataItem != null) { var bytes = outputBytes.Skip(currentDataItem.DataIndexStart).ToArray(); currentDataItem.Result = currentDataItem.Parameter.ABIType.Decode(bytes, currentDataItem.Parameter.DecodedType); } return(outputParameters.ToList()); }
public List <ParameterOutput> DecodeOutput(byte[] outputBytes, params ParameterOutput[] outputParameters) { var currentIndex = 0; Array.Sort(outputParameters, (x, y) => x.Parameter.Order.CompareTo(y.Parameter.Order)); foreach (var outputParam in outputParameters) { var param = outputParam.Parameter; if (param.ABIType.IsDynamic()) { outputParam.DataIndexStart = EncoderDecoderHelpers.GetNumberOfBytes(outputBytes.Skip(currentIndex).ToArray()); currentIndex = currentIndex + 32; } else { var bytes = outputBytes.Skip(currentIndex).Take(param.ABIType.FixedSize).ToArray(); outputParam.Result = param.ABIType.Decode(bytes, outputParam.Parameter.DecodedType); currentIndex = currentIndex + param.ABIType.FixedSize; } } ParameterOutput currentDataItem = null; foreach ( var nextDataItem in outputParameters.Where(outputParam => outputParam.Parameter.ABIType.IsDynamic())) { if (currentDataItem != null) { var bytes = outputBytes.Skip(currentDataItem.DataIndexStart).Take(nextDataItem.DataIndexStart - currentDataItem.DataIndexStart).ToArray(); currentDataItem.Result = currentDataItem.Parameter.ABIType.Decode(bytes, currentDataItem.Parameter.DecodedType); } currentDataItem = nextDataItem; } if (currentDataItem != null) { var bytes = outputBytes.Skip(currentDataItem.DataIndexStart).ToArray(); currentDataItem.Result = currentDataItem.Parameter.ABIType.Decode(bytes, currentDataItem.Parameter.DecodedType); } return(outputParameters.ToList()); }
public List <ParameterOutput> DecodeDefaultTopics(Parameter[] inputParameters, object[] topics, string data) { var parameterOutputs = new List <ParameterOutput>(); var indexedParameters = inputParameters.Where(x => x.Indexed == true).OrderBy(x => x.Order).ToArray(); var dataParameters = inputParameters.Where(x => x.Indexed == false).OrderBy(x => x.Order).ToArray(); // Take one off topics count to skip signature var topicCount = (topics.Length - 1); var indexedPropertiesCount = indexedParameters.Length; if (indexedPropertiesCount != (topicCount)) { throw new Exception($"Number of indexes don't match the number of topics. Indexed Properties {indexedPropertiesCount}, Topics : {topicCount}"); } var topicNumber = 0; foreach (var topic in topics) { //skip the first one as it is the signature if (topicNumber > 0) { var parameter = indexedParameters[topicNumber - 1]; //skip dynamic types as the topic value is the sha3 keccak if (!parameter.ABIType.IsDynamic()) { parameterOutputs.Add(DecodeDefaultData(topic.ToString(), parameter).FirstOrDefault()); } else { var parameterOutput = new ParameterOutput() { Parameter = parameter, Result = topic.ToString() }; parameterOutputs.Add(parameterOutput); } } topicNumber = topicNumber + 1; } parameterOutputs.AddRange(DecodeDefaultData(data, dataParameters.ToArray())); return(parameterOutputs); }
public T DecodeSimpleTypeOutput <T>(Parameter outputParameter, string output) { if (output == "0x") { return(default(T)); } ThrowIfErrorOnOutput(output); if (outputParameter != null) { outputParameter.DecodedType = typeof(T); var parmeterOutput = new ParameterOutput { Parameter = outputParameter }; if (outputParameter.ABIType is TupleType tupleType) { if (typeof(T) == typeof(List <ParameterOutput>)) { var results = DecodeOutput(output, parmeterOutput); if (results.Any()) { return((T)results[0].Result); } } else { return((T)DecodeAttributes(output.HexToByteArray().Skip(32).ToArray(), typeof(T))); } } else { var results = DecodeOutput(output, parmeterOutput); if (results.Any()) { return((T)results[0].Result); } } } return(default(T)); }
///<summary> /// Decodes the output of a function using either a FunctionOutputAttribute (T) /// or the parameter casted to the type T, only one outputParameter should be used in this scenario. /// </summary> /// public T DecodeOutput <T>(string output, params Parameter[] outputParameter) where T : new() { if (output == "0x") { return(default(T)); } var function = FunctionOutputAttribute.GetAttribute <T>(); if (function == null) { if (outputParameter != null) { if (outputParameter.Length > 1) { throw new Exception( "Only one output parameter supported to be decoded this way, use a FunctionOutputAttribute or define each outputparameter"); } var parmeterOutput = new ParameterOutput() { DecodedType = typeof(T), Parameter = outputParameter[0] }; var results = DecodeOutput(output, parmeterOutput); if (results.Any()) { return((T)results[0].Result); } } return(default(T)); } else { return(DecodeOutput <T>(output)); } }