using System; using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.Linq; namespace Nethereum.Unity.RpcModel { /* 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. */ internal 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 RpcResponse 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 (Exception ex) { throw new Exception("Unable to convert the result to type " + typeof(T), ex); } } } [JsonObject] internal class RpcResponse { [JsonConstructor] protected RpcResponse() { JsonRpcVersion = "2.0"; } /// Request id protected RpcResponse(object id) { this.Id = id; JsonRpcVersion = "2.0"; } /// Request id /// Request error public RpcResponse(object id, RpcError error) : this(id) { this.Error = error; } /// Request id /// Response result object public RpcResponse(object id, JToken result) : this(id) { this.Result = result; } /// /// Request id (Required but nullable) /// [JsonProperty("id", Required = Required.AllowNull)] 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)] //TODO somehow enforce this or an error, not both public JToken Result { get; private set; } /// /// Error from processing Rpc request (Required) /// [JsonProperty("error", Required = Required.Default)] public RpcError Error { get; private set; } [JsonIgnore] public bool HasError { get{ return this.Error != null;}} } [JsonObject] internal class RpcRequest { [JsonConstructor] private RpcRequest() { } /// Request id /// Target method name /// List of parameters for the target method public RpcRequest(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 RpcRequest(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 /// internal 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] internal class RpcError { [JsonConstructor] private RpcError() { } /// /// Rpc error code (Required) /// [JsonProperty("code", Required = Required.Always)] 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; } } }