加粗样式 web3js 是自带 BatchRequest 的封装的,
奈何C# 并没有所以自己封装了一个差不多的,
目前完成了部分接口,也算是提供了一个思路
/// <summary>
/// 演示
/// </summary>
public async void Demo()
BatchRequest.cs 代码例子
using Common;
using System.Text;
using static Web3LogsSubscribe3.Models.BatchRequestModels;
using static Web3LogsSubscribe3.Models.BatchRequestModels.JsonRpcReq;
namespace Web3LogsSubscribe
{
public class BatchRequest : Web3Request
{
/// <summary>
/// 网络对象
/// </summary>
HttpClient _httpClient;
/// <summary>
/// 请求数据
/// </summary>
private List<JsonRpcReq> reqData = new List<JsonRpcReq>();
public BatchRequest(string url)
{
lock (Web3RequestEx.Url)
{
Web3RequestEx.Url = url;
}
_httpClient = new HttpClient()
{
BaseAddress = new Uri(url)
};
}
/// <summary>
/// 释放批量请求
/// </summary>
public void Clear()
{
reqData.Clear();
}
/// <summary>
/// 添加批量转账请求
/// </summary>
/// <param name="jsonRpcReq"></param>
/// <returns></returns>
public JsonRpcReq[] Add(params JsonRpcReq[] jsonRpcReq)
{
lock (reqData)
{
foreach (var item in jsonRpcReq)
{
item.id = reqData.Count() + 1;
reqData.Add(item);
}
}
return jsonRpcReq;
}
/// <summary>
/// 发送请求
/// </summary>
/// <returns></returns>
public async Task<List<JsonRpcReq>> SendRequestAsync() => await reqData.SendRequestAsync(Web3RequestEx.Url);
/// <summary>
/// 演示
/// </summary>
public async void Demo()
{
var addr = "0xe3778dd4350592db6f6767ec73a9981076efab2d";
var txhash = "0xe4e20d5503698d88a53b1436aad6c33c2720f57fe1145448f644114d9af3bc47";
// 批量请求
var batchRequest = new BatchRequest("https://rpc.ankr.com/bsc/");
var hash = batchRequest.Add(
BatchRequest.eth_getBalance(addr, (err, res) =>
{
Console.WriteLine($"BatchRequest.eth_getBalance : {res}");
})
, BatchRequest.eth_getTransactionByHash(txhash, (err, res) =>
{
Console.WriteLine($"BatchRequest.eth_getBalance : {res.ToJson()}");
})
);
var res1 = await batchRequest.SendRequestAsync();
// 单个请求
var res2 = await Web3Request.eth_getBalance(addr, (err, res) =>
{
Console.WriteLine($"Web3Request.eth_getBalance : {res}");
}).SendRequestAsync();
var res3 = await Web3Request.eth_getTransactionByHash(txhash, (err, res) =>
{
Console.WriteLine($"Web3Request.eth_getTransactionByHash : {res.ToJson()}");
}).SendRequestAsync();
}
}
public static class Web3RequestEx
{
/// <summary>
/// 单个请求时 必须先设置Url
/// </summary>
public static string Url = "";
/// <summary>
/// 发送请求
/// </summary>
/// <returns></returns>
public static async Task<List<JsonRpcReq>> SendRequestAsync(this List<JsonRpcReq> reqData, string url = "")
{
if (string.IsNullOrEmpty(url)) url = Web3RequestEx.Url;
else Web3RequestEx.Url = url;
if (string.IsNullOrEmpty(url)) throw new Exception("需要提供url参数,或赋值 Web3RequestEx.Url");
try
{
var _httpClient = new HttpClient();
var content = new StringContent(reqData.ToJson(), Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync(url, content);
var responseJson = await response.Content.ReadAsStringAsync();
var resObj = responseJson.ToObject<List<JsonRpcRes>>();
// 处理结果
for (int i = 0; i < resObj.Count; i++)
{
try
{
reqData[i].result = resObj[i];
reqData[i].callback(resObj[i].error, reqData[i].result?.result);
}
catch (Exception ex)
{
Console.WriteLine($"批量请求处理异常: {ex.Message}");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return reqData;
}
/// <summary>
/// 发送请求
/// </summary>
/// <returns></returns>
public static async Task<List<JsonRpcReq>> SendRequestAsync(this JsonRpcReq reqData, string url = "")
=> await SendRequestAsync((new List<JsonRpcReq>() { reqData }), url != "" ? url : Web3RequestEx.Url);
/// <summary>
/// 添加批量请求
/// </summary>
public static JsonRpcReq GenJsonRpcReq(string method, Action<JsonRpcRes.Error?, object?> callback, params object[] paramList)
{
var list = new List<object>();
// 过滤null参数
foreach (var item in paramList) if (item != null) list.Add(item);
return new JsonRpcReq()
{
jsonrpc = "2.0",
id = 1,
method = method,
@params = list.ToArray(),
callback = callback,
};
}
}
public class Web3Request
{
/// <summary>
/// 订阅消息
/// </summary>
public static JsonRpcReq eth_subscribe(string type, object? ex = null, Action<JsonRpcRes.Error?, string?>? callback = null)
{
return Web3RequestEx.GenJsonRpcReq(System.Reflection.MethodBase.GetCurrentMethod()!.Name,
(err, res) => callback?.Invoke(err, res?.ToString()),
type, ex
);
}
/// <summary>
/// 订阅日志
/// </summary>
public static JsonRpcReq eth_subscribe_logs(string address, string topics, Action<JsonRpcRes.Error?, string?>? callback = null)
{
return eth_subscribe_logs(new string[] { address }, new string[] { topics }, callback);
}
public static JsonRpcReq eth_subscribe_logs(string[] address, string[] topics, Action<JsonRpcRes.Error?, string?>? callback = null)
{
return eth_subscribe("logs",
(new LogsSubscribeReq
{
address = address,
topics = topics
}));
}
/// <summary>
/// 查询主网余额
/// </summary>
public static JsonRpcReq eth_getBalance(string addr, Action<JsonRpcRes.Error?, string?>? callback = null)
{
return Web3RequestEx.GenJsonRpcReq(System.Reflection.MethodBase.GetCurrentMethod()!.Name,
(err, res) => callback?.Invoke(err, res?.ToString()),
addr, "latest"
);
}
/// <summary>
/// 查询哈希信息
/// </summary>
public static JsonRpcReq eth_getTransactionByHash(string txhash, Action<JsonRpcRes.Error?, JsonRpcRes.GetTransactionByHashRes?>? callback = null)
{
return Web3RequestEx.GenJsonRpcReq(System.Reflection.MethodBase.GetCurrentMethod()!.Name,
(err, res) => callback?.Invoke(err, res?.ToString()!.ToObject<JsonRpcRes.GetTransactionByHashRes>()),
txhash
);
}
/// <summary>
/// 查询哈希信息
/// </summary>
public static JsonRpcReq eth_getCode(string addr, Action<JsonRpcRes.Error?, JsonRpcRes.GetTransactionByHashRes?>? callback = null)
{
return Web3RequestEx.GenJsonRpcReq(System.Reflection.MethodBase.GetCurrentMethod()!.Name,
(err, res) => callback?.Invoke(err, res?.ToString()!.ToObject<JsonRpcRes.GetTransactionByHashRes>()),
addr,"latest"
);
}
}
}
模型
using System.Text.Json.Serialization;
namespace Web3LogsSubscribe3.Models
{
public class BatchRequestModels
{
/// <summary>
/// Web3请求包体
/// </summary>
public class JsonRpcReq
{
public string jsonrpc { get; set; }
public int id { get; set; }
public string method { get; set; }
public object[] @params { get; set; }
[JsonIgnore]
public Action<JsonRpcRes.Error?, object?> callback { get; set; }
[JsonIgnore]
public JsonRpcRes? result { get; set; }
public class LogsSubscribeReq
{
public string[] address { get; set; }
public object[] topics { get; set; }
}
}
/// <summary>
/// WEB3响应包体
/// </summary>
public class JsonRpcRes
{
public string jsonrpc { get; set; }
public int id { get; set; }
public object result { get; set; }
public Error error { get; set; }
public class Error
{
public int code { get; set; }
public string message { get; set; }
}
public class GetTransactionByHashRes
{
public string BlockHash { get; set; }
public string BlockNumber { get; set; }
public string From { get; set; }
public string Gas { get; set; }
public string GasPrice { get; set; }
public string Hash { get; set; }
public string Input { get; set; }
public string Nonce { get; set; }
public string To { get; set; }
public string TransactionIndex { get; set; }
public string Value { get; set; }
public string Type { get; set; }
public string ChainId { get; set; }
public string V { get; set; }
public string R { get; set; }
public string S { get; set; }
}
}
}
}