- Coin: Zano → Lethean, ticker: ZAN/ZANO → LTHN - Ports: 11211 → 36941 (mainnet RPC), 46941 (testnet RPC) - Wallet: 11212 → 36944/46944 - Address prefix: iTHN - URLs: zano.org → lethean.io - Explorer links: explorer.lthn.io Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
114 lines
3.6 KiB
C#
114 lines
3.6 KiB
C#
using System;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Headers;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Serialization;
|
|
|
|
namespace BTCPayServer.Plugins.Lethean.RPC
|
|
{
|
|
public class JsonRpcClient
|
|
{
|
|
private readonly Uri _address;
|
|
private readonly HttpClient _httpClient;
|
|
|
|
public JsonRpcClient(Uri address, HttpClient client = null)
|
|
{
|
|
_address = address;
|
|
_httpClient = client ?? new HttpClient();
|
|
}
|
|
|
|
|
|
public async Task<TResponse> SendCommandAsync<TRequest, TResponse>(string method, TRequest data,
|
|
CancellationToken cts = default)
|
|
{
|
|
var jsonSerializer = new JsonSerializerSettings
|
|
{
|
|
ContractResolver = new CamelCasePropertyNamesContractResolver()
|
|
};
|
|
var httpRequest = new HttpRequestMessage()
|
|
{
|
|
Method = HttpMethod.Post,
|
|
RequestUri = new Uri(_address, "json_rpc"),
|
|
Content = new StringContent(
|
|
JsonConvert.SerializeObject(new JsonRpcCommand<TRequest>(method, data), jsonSerializer),
|
|
Encoding.UTF8, "application/json")
|
|
};
|
|
httpRequest.Headers.Accept.Clear();
|
|
httpRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
|
|
|
HttpResponseMessage rawResult = await _httpClient.SendAsync(httpRequest, cts);
|
|
rawResult.EnsureSuccessStatusCode();
|
|
var rawJson = await rawResult.Content.ReadAsStringAsync();
|
|
|
|
JsonRpcResult<TResponse> response;
|
|
try
|
|
{
|
|
response = JsonConvert.DeserializeObject<JsonRpcResult<TResponse>>(rawJson, jsonSerializer);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine(e.Message);
|
|
Console.WriteLine(rawJson);
|
|
throw;
|
|
}
|
|
|
|
if (response.Error != null)
|
|
{
|
|
throw new JsonRpcApiException()
|
|
{
|
|
Error = response.Error
|
|
};
|
|
}
|
|
|
|
return response.Result;
|
|
}
|
|
|
|
public class NoRequestModel
|
|
{
|
|
public static readonly NoRequestModel Instance = new();
|
|
}
|
|
|
|
public class JsonRpcApiException : Exception
|
|
{
|
|
public JsonRpcResultError Error { get; set; }
|
|
|
|
public override string Message => Error?.Message;
|
|
}
|
|
|
|
public class JsonRpcResultError
|
|
{
|
|
[JsonProperty("code")] public int Code { get; set; }
|
|
[JsonProperty("message")] public string Message { get; set; }
|
|
[JsonProperty("data")] dynamic Data { get; set; }
|
|
}
|
|
internal class JsonRpcResult<T>
|
|
{
|
|
[JsonProperty("result")] public T Result { get; set; }
|
|
[JsonProperty("error")] public JsonRpcResultError Error { get; set; }
|
|
[JsonProperty("id")] public string Id { get; set; }
|
|
}
|
|
|
|
internal class JsonRpcCommand<T>
|
|
{
|
|
[JsonProperty("jsonrpc")] public string JsonRpc { get; set; } = "2.0";
|
|
[JsonProperty("id")] public string Id { get; set; } = Guid.NewGuid().ToString();
|
|
[JsonProperty("method")] public string Method { get; set; }
|
|
|
|
[JsonProperty("params")] public T Parameters { get; set; }
|
|
|
|
public JsonRpcCommand()
|
|
{
|
|
}
|
|
|
|
public JsonRpcCommand(string method, T parameters)
|
|
{
|
|
Method = method;
|
|
Parameters = parameters;
|
|
}
|
|
}
|
|
}
|
|
}
|