using System; using System.Collections.Generic; using System.Text; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace Nethereum.JsonRpc.Client.RpcMessages { /* RPC Model simplified and downported to net351 from EdjCase.JsonRPC.Core https://github.com/edjCase/JsonRpc/tree/master/src/EdjCase.JsonRpc.Core The MIT License (MIT) Copyright(c) 2015 Gekctek Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ public static class RpcResponseExtensions { /// /// Parses and returns the result of the rpc response as the type specified. /// Otherwise throws a parsing exception /// /// Type of object to parse the response as /// Rpc response object /// Returns the type's default value if the result is null. Otherwise throws parsing exception /// Result of response as type specified public static T GetResult(this RpcResponseMessage response, bool returnDefaultIfNull = true, JsonSerializerSettings settings = null) { if (response.Result == null) { if (!returnDefaultIfNull && default(T) != null) { throw new Exception("Unable to convert the result (null) to type " + typeof(T)); } return default(T); } try { if (settings == null) { return response.Result.ToObject(); } else { JsonSerializer jsonSerializer = JsonSerializer.Create(settings); return response.Result.ToObject(jsonSerializer); } } catch (FormatException ex) { throw new FormatException("Invalid format when trying to convert the result to type " + typeof(T), ex); } catch (Exception ex) { throw new Exception("Unable to convert the result to type " + typeof(T), ex); } } /// /// Parses and returns the result of the rpc streaming response as the type specified. /// Otherwise throws a parsing exception /// /// Type of object to parse the response as /// Rpc response object /// Returns the type's default value if the result is null. Otherwise throws parsing exception /// Result of response as type specified public static T GetStreamingResult(this RpcStreamingResponseMessage response, bool returnDefaultIfNull = true, JsonSerializerSettings settings = null) { if(response.Method == null) { return GetResult(response, returnDefaultIfNull, settings); } if (response.Params.Result == null) { if (!returnDefaultIfNull && default(T) != null) { throw new Exception("Unable to convert the result (null) to type " + typeof(T)); } return default(T); } try { if (settings == null) { return response.Params.Result.ToObject(); } else { JsonSerializer jsonSerializer = JsonSerializer.Create(settings); return response.Params.Result.ToObject(jsonSerializer); } } catch (FormatException ex) { throw new FormatException("Invalid format when trying to convert the result to type " + typeof(T), ex); } catch (Exception ex) { throw new Exception("Unable to convert the result to type " + typeof(T), ex); } } } [JsonObject] public class RpcResponseMessage { [JsonConstructor] protected RpcResponseMessage() { JsonRpcVersion = "2.0"; } /// Request id protected RpcResponseMessage(object id) { this.Id = id; JsonRpcVersion = "2.0"; } /// Request id /// Request error public RpcResponseMessage(object id, RpcError error) : this(id) { this.Error = error; } /// Request id /// Response result object public RpcResponseMessage(object id, JToken result) : this(id) { this.Result = result; } /// /// Request id (Required but nullable) /// [JsonProperty("id", Required = Required.Default)] public object Id { get; private set; } /// /// Rpc request version (Required) /// [JsonProperty("jsonrpc", Required = Required.Always)] public string JsonRpcVersion { get; private set; } /// /// Reponse result object (Required) /// [JsonProperty("result", Required = Required.Default)] public JToken Result { get; private set; } /// /// Error from processing Rpc request (Required) /// [JsonProperty("error", Required = Required.Default)] public RpcError Error { get; protected set; } [JsonIgnore] public bool HasError { get { return this.Error != null; } } } [JsonObject] public class RpcStreamingResponseMessage : RpcResponseMessage { [JsonConstructor] protected RpcStreamingResponseMessage() { } /// Request error public RpcStreamingResponseMessage(RpcError error) : base() { this.Error = error; } /// method name /// Response result object public RpcStreamingResponseMessage(string method, RpcStreamingParams @params) : base() { this.Method = method; this.Params = @params; } /// /// Rpc request version (Required) /// [JsonProperty("method", Required = Required.Default)] public string Method { get; private set; } /// /// Reponse result object (Required) /// [JsonProperty("params", Required = Required.Default)] public RpcStreamingParams Params { get; private set; } } [JsonObject] public class RpcStreamingParams { [JsonConstructor] public RpcStreamingParams() { } /// /// Response Subscription Id (Required) /// [JsonProperty("subscription", Required = Required.Always)] public string Subscription { get; private set; } /// /// Reponse result object (Required) /// [JsonProperty("result", Required = Required.Always)] public JToken Result { get; private set; } } [JsonObject] public class RpcRequestMessage { [JsonConstructor] private RpcRequestMessage() { } /// Request id /// Target method name /// List of parameters for the target method public RpcRequestMessage(object id, string method, params object[] parameterList) { this.Id = id; this.JsonRpcVersion = "2.0"; this.Method = method; this.RawParameters = parameterList; } /// Request id /// Target method name /// Map of parameter name to parameter value for the target method public RpcRequestMessage(object id, string method, Dictionary parameterMap) { this.Id = id; this.JsonRpcVersion = "2.0"; this.Method = method; this.RawParameters = parameterMap; } /// /// Request Id (Optional) /// [JsonProperty("id")] public object Id { get; private set; } /// /// Version of the JsonRpc to be used (Required) /// [JsonProperty("jsonrpc", Required = Required.Always)] public string JsonRpcVersion { get; private set; } /// /// Name of the target method (Required) /// [JsonProperty("method", Required = Required.Always)] public string Method { get; private set; } /// /// Parameters to invoke the method with (Optional) /// [JsonProperty("params")] [JsonConverter(typeof(RpcParametersJsonConverter))] public object RawParameters { get; private set; } } /// /// Json converter for Rpc parameters /// public class RpcParametersJsonConverter : JsonConverter { /// /// Writes the value of the parameters to json format /// /// Json writer /// Value to be converted to json format /// Json serializer public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { serializer.Serialize(writer, value); } /// /// Read the json format and return the correct object type/value for it /// /// Json reader /// Type of property being set /// The current value of the property being set /// Json serializer /// The object value of the converted json value public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { switch (reader.TokenType) { case JsonToken.StartObject: try { JObject jObject = JObject.Load(reader); return jObject.ToObject>(); } catch (Exception) { throw new Exception("Request parameters can only be an associative array, list or null."); } case JsonToken.StartArray: return JArray.Load(reader).ToObject(serializer); case JsonToken.Null: return null; } throw new Exception("Request parameters can only be an associative array, list or null."); } /// /// Determines if the type can be convertered with this converter /// /// Type of the object /// True if the converter converts the specified type, otherwise False public override bool CanConvert(Type objectType) { return true; } } [JsonObject] public class RpcError { [JsonConstructor] private RpcError() { } /// /// Rpc error code /// [JsonProperty("code")] public int Code { get; private set; } /// /// Error message (Required) /// [JsonProperty("message", Required = Required.Always)] public string Message { get; private set; } /// /// Error data (Optional) /// [JsonProperty("data")] public JToken Data { get; private set; } } }