From 7460ac20aa5ce6939021e46d08d17ddd6c09adfe Mon Sep 17 00:00:00 2001 From: felix-zhaolei Date: Wed, 18 Dec 2024 10:40:06 +0800 Subject: [PATCH 1/2] feat: request to node. --- .../Commons/AelfClientConstant.cs | 7 + .../CAServerApplicationModule.cs | 3 + .../Common/AelfClient/IContractClient.cs | 30 +++ .../AelfClient/IContractClientSelector.cs | 28 +++ .../AelfClient/MainChainContractClient.cs | 183 ++++++++++++++++++ .../AelfClient/SideChainContractClient.cs | 183 ++++++++++++++++++ .../ContractService/ContractService.cs | 21 +- .../Application/IContractProvider.cs | 41 ++-- .../CAServerContractEventHandlerCoreModule.cs | 29 +++ 9 files changed, 503 insertions(+), 22 deletions(-) create mode 100644 src/CAServer.Application.Contracts/Commons/AelfClientConstant.cs create mode 100644 src/CAServer.Application/Common/AelfClient/IContractClient.cs create mode 100644 src/CAServer.Application/Common/AelfClient/IContractClientSelector.cs create mode 100644 src/CAServer.Application/Common/AelfClient/MainChainContractClient.cs create mode 100644 src/CAServer.Application/Common/AelfClient/SideChainContractClient.cs diff --git a/src/CAServer.Application.Contracts/Commons/AelfClientConstant.cs b/src/CAServer.Application.Contracts/Commons/AelfClientConstant.cs new file mode 100644 index 000000000..ff1a0d0e0 --- /dev/null +++ b/src/CAServer.Application.Contracts/Commons/AelfClientConstant.cs @@ -0,0 +1,7 @@ +namespace CAServer.Commons; + +public static class AelfClientConstant +{ + public const string MainChainClient = "MainChainClient"; + public const string SideChainClient = "SideChainClient"; +} \ No newline at end of file diff --git a/src/CAServer.Application/CAServerApplicationModule.cs b/src/CAServer.Application/CAServerApplicationModule.cs index 5e7413972..7633e2245 100644 --- a/src/CAServer.Application/CAServerApplicationModule.cs +++ b/src/CAServer.Application/CAServerApplicationModule.cs @@ -6,6 +6,7 @@ using CAServer.CAAccount.Provider; using CAServer.Cache; using CAServer.Common; +using CAServer.Common.AelfClient; using CAServer.Commons; using CAServer.CryptoGift; using CAServer.DataReporting; @@ -173,6 +174,8 @@ public override void ConfigureServices(ServiceConfigurationContext context) context.Services.AddScoped(); context.Services.AddScoped(); context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); Configure(configuration.GetSection("Variables")); context.Services.AddScoped(); diff --git a/src/CAServer.Application/Common/AelfClient/IContractClient.cs b/src/CAServer.Application/Common/AelfClient/IContractClient.cs new file mode 100644 index 000000000..b87d627fc --- /dev/null +++ b/src/CAServer.Application/Common/AelfClient/IContractClient.cs @@ -0,0 +1,30 @@ +using System; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using AElf.Client.Dto; +using AElf.Types; +using Google.Protobuf; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using ChainOptions = CAServer.Options.ChainOptions; + +namespace CAServer.Common.AelfClient; + +public interface IContractClient +{ + Task GenerateTransactionAsync( + string from, + string to, + string methodName, + IMessage input); + + Task GetBlockByHeightAsync(long blockHeight, bool includeTransactions = false); + + Task SendTransactionAsync(SendTransactionInput input); + + Task GetTransactionResultAsync(string transactionId); + Task ExecuteTransactionAsync(ExecuteTransactionDto input); +} + diff --git a/src/CAServer.Application/Common/AelfClient/IContractClientSelector.cs b/src/CAServer.Application/Common/AelfClient/IContractClientSelector.cs new file mode 100644 index 000000000..590c81eeb --- /dev/null +++ b/src/CAServer.Application/Common/AelfClient/IContractClientSelector.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.Linq; +using CAServer.Commons; +using Volo.Abp.DependencyInjection; + +namespace CAServer.Common.AelfClient; + +public interface IContractClientSelector +{ + IContractClient GetContractClient(string chainId); +} + +public class ContractClientSelector : IContractClientSelector, ISingletonDependency +{ + private readonly IEnumerable _contractClients; + + public ContractClientSelector(IEnumerable contractClients) + { + _contractClients = contractClients; + } + + public IContractClient GetContractClient(string chainId) + { + return chainId == CommonConstant.MainChainId + ? _contractClients.FirstOrDefault(t => t.GetType().Name == nameof(MainChainContractClient)) + : _contractClients.FirstOrDefault(t => t.GetType().Name == nameof(SideChainContractClient)); + } +} \ No newline at end of file diff --git a/src/CAServer.Application/Common/AelfClient/MainChainContractClient.cs b/src/CAServer.Application/Common/AelfClient/MainChainContractClient.cs new file mode 100644 index 000000000..bece00d68 --- /dev/null +++ b/src/CAServer.Application/Common/AelfClient/MainChainContractClient.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Net.Mime; +using System.Text; +using System.Threading.Tasks; +using AElf.Client.Dto; +using AElf.Types; +using CAServer.Commons; +using Google.Protobuf; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using Volo.Abp; + +namespace CAServer.Common.AelfClient; + +public class MainChainContractClient : IContractClient +{ + private readonly IHttpClientFactory _httpClientFactory; + private readonly ILogger _logger; + + public MainChainContractClient(IHttpClientFactory httpClientFactory, ILogger logger) + { + _httpClientFactory = httpClientFactory; + _logger = logger; + } + + public async Task GenerateTransactionAsync( + string from, + string to, + string methodName, + IMessage input) + { + try + { + var chainStatusAsync = await GetChainStatusAsync(); + return new Transaction() + { + From = Address.FromBase58(from), + To = Address.FromBase58(to), + MethodName = methodName, + Params = input.ToByteString(), + RefBlockNumber = chainStatusAsync.BestChainHeight, + RefBlockPrefix = ByteString.CopyFrom(Hash.LoadFromHex(chainStatusAsync.BestChainHash).Value + .Take(4).ToArray()) + }; + } + catch (Exception ex) + { + _logger.LogError(ex, "[ContractClient.GenerateTransactionAsync] error, msg:{0},trace:{1}", ex.Message, + ex.StackTrace ?? "-"); + return (Transaction)null; + } + } + + public async Task GetBlockByHeightAsync(long blockHeight, bool includeTransactions = false) + { + var uri = string.Format("api/blockChain/blockByHeight?blockHeight={0}&includeTransactions={1}", + blockHeight, includeTransactions); + return await GetAsync(uri); + } + + public async Task SendTransactionAsync(SendTransactionInput input) + { + var uri = "api/blockChain/sendTransaction"; + var param = new Dictionary() + { + { + "RawTransaction", + input.RawTransaction + } + }; + var result = await PostAsync(uri, param); + return result; + } + + public async Task GetTransactionResultAsync(string transactionId) + { + var url = "api/blockChain/transactionResult?transactionId=" + transactionId; + var res = await GetAsync(url); + return res; + } + + public async Task ExecuteTransactionAsync(ExecuteTransactionDto input) + { + var url = "api/blockChain/executeTransaction"; + var param = new Dictionary() + { + { + "RawTransaction", + input.RawTransaction + } + }; + var res = await PostAsync(url,param); + return res; + } + + public async Task GetChainStatusAsync() + { + var uri = "api/blockChain/chainStatus"; + return await GetAsync(uri); + } + + public async Task GetAsync(string url) + { + _logger.LogInformation("[MainChainContractClient] GetAsync begin:{url}", url); + var client = _httpClientFactory.CreateClient(AelfClientConstant.MainChainClient); + var response = await client.GetAsync(url); + var content = await response.Content.ReadAsStringAsync(); + if (!ResponseSuccess(response.StatusCode)) + { + _logger.LogError( + "[ContractClientError] GetError Response not success, url:{url}, code:{code}, message: {message}", + url, response.StatusCode, content); + + throw new UserFriendlyException(content, ((int)response.StatusCode).ToString()); + } + + _logger.LogInformation("[MainChainContractClient] GetAsync end:{url}", url); + return JsonConvert.DeserializeObject(content); + } + + public async Task PostAsync(string url, object paramObj) + { + _logger.LogInformation("[MainChainContractClient] PostAsync begin:{url}", url); + var requestInput = paramObj == null ? string.Empty : JsonConvert.SerializeObject(paramObj, Formatting.None); + + var requestContent = new StringContent( + requestInput, + Encoding.UTF8, + MediaTypeNames.Application.Json); + + var client = _httpClientFactory.CreateClient(AelfClientConstant.MainChainClient); + + var response = await client.PostAsync(url, requestContent); + var content = await response.Content.ReadAsStringAsync(); + + if (!ResponseSuccess(response.StatusCode)) + { + _logger.LogError( + "[ContractClientError] PostError Response not success, url:{url}, code:{code}, message: {message}, params:{param}", + url, response.StatusCode, content, JsonConvert.SerializeObject(paramObj)); + + throw new UserFriendlyException(content, ((int)response.StatusCode).ToString()); + } + + _logger.LogInformation("[MainChainContractClient] PostAsync end:{url}", url); + return JsonConvert.DeserializeObject(content); + } + + public async Task PostAsync(string url, object paramObj) + { + _logger.LogInformation("[MainChainContractClient] PostAsync begin:{url}", url); + var requestInput = paramObj == null ? string.Empty : JsonConvert.SerializeObject(paramObj, Formatting.None); + + var requestContent = new StringContent( + requestInput, + Encoding.UTF8, + MediaTypeNames.Application.Json); + + var client = _httpClientFactory.CreateClient(AelfClientConstant.MainChainClient); + + var response = await client.PostAsync(url, requestContent); + var content = await response.Content.ReadAsStringAsync(); + + if (!ResponseSuccess(response.StatusCode)) + { + _logger.LogError( + "[ContractClientError] PostError Response not success, url:{url}, code:{code}, message: {message}, params:{param}", + url, response.StatusCode, content, JsonConvert.SerializeObject(paramObj)); + + throw new UserFriendlyException(content, ((int)response.StatusCode).ToString()); + } + + _logger.LogInformation("[MainChainContractClient] PostAsync end:{url}", url); + return content; + } + + private bool ResponseSuccess(HttpStatusCode statusCode) => + statusCode is HttpStatusCode.OK or HttpStatusCode.NoContent; +} \ No newline at end of file diff --git a/src/CAServer.Application/Common/AelfClient/SideChainContractClient.cs b/src/CAServer.Application/Common/AelfClient/SideChainContractClient.cs new file mode 100644 index 000000000..d0d580dd3 --- /dev/null +++ b/src/CAServer.Application/Common/AelfClient/SideChainContractClient.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Net.Mime; +using System.Text; +using System.Threading.Tasks; +using AElf.Client.Dto; +using AElf.Types; +using CAServer.Commons; +using Google.Protobuf; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using Volo.Abp; + +namespace CAServer.Common.AelfClient; + +public class SideChainContractClient : IContractClient +{ + private readonly IHttpClientFactory _httpClientFactory; + private readonly ILogger _logger; + + public SideChainContractClient(IHttpClientFactory httpClientFactory, ILogger logger) + { + _httpClientFactory = httpClientFactory; + _logger = logger; + } + + public async Task GenerateTransactionAsync( + string from, + string to, + string methodName, + IMessage input) + { + try + { + var chainStatusAsync = await GetChainStatusAsync(); + return new Transaction() + { + From = Address.FromBase58(from), + To = Address.FromBase58(to), + MethodName = methodName, + Params = input.ToByteString(), + RefBlockNumber = chainStatusAsync.BestChainHeight, + RefBlockPrefix = ByteString.CopyFrom(Hash.LoadFromHex(chainStatusAsync.BestChainHash).Value + .Take(4).ToArray()) + }; + } + catch (Exception ex) + { + _logger.LogError(ex, "[ContractClient.GenerateTransactionAsync] error, msg:{0},trace:{1}", ex.Message, + ex.StackTrace ?? "-"); + return (Transaction)null; + } + } + + public async Task GetBlockByHeightAsync(long blockHeight, bool includeTransactions = false) + { + var uri = string.Format("api/blockChain/blockByHeight?blockHeight={0}&includeTransactions={1}", + blockHeight, includeTransactions); + return await GetAsync(uri); + } + + public async Task SendTransactionAsync(SendTransactionInput input) + { + var uri = "api/blockChain/sendTransaction"; + var param = new Dictionary() + { + { + "RawTransaction", + input.RawTransaction + } + }; + var result = await PostAsync(uri, param); + return result; + } + + public async Task GetTransactionResultAsync(string transactionId) + { + var url = "api/blockChain/transactionResult?transactionId=" + transactionId; + var res = await GetAsync(url); + return res; + } + + public async Task ExecuteTransactionAsync(ExecuteTransactionDto input) + { + var url = "api/blockChain/executeTransaction"; + var param = new Dictionary() + { + { + "RawTransaction", + input.RawTransaction + } + }; + var res = await PostAsync(url, param); + return res; + } + + public async Task GetChainStatusAsync() + { + var uri = "api/blockChain/chainStatus"; + return await GetAsync(uri); + } + + public async Task GetAsync(string url) + { + _logger.LogInformation("[SideChainContractClient] GetAsync begin:{url}", url); + var client = _httpClientFactory.CreateClient(AelfClientConstant.SideChainClient); + var response = await client.GetAsync(url); + var content = await response.Content.ReadAsStringAsync(); + if (!ResponseSuccess(response.StatusCode)) + { + _logger.LogError( + "[ContractClientError] GetError Response not success, url:{url}, code:{code}, message: {message}", + url, response.StatusCode, content); + + throw new UserFriendlyException(content, ((int)response.StatusCode).ToString()); + } + + _logger.LogInformation("[SideChainContractClient] GetAsync end:{url}", url); + return JsonConvert.DeserializeObject(content); + } + + public async Task PostAsync(string url, object paramObj) + { + _logger.LogInformation("[SideChainContractClient] PostAsync begin:{url}", url); + var requestInput = paramObj == null ? string.Empty : JsonConvert.SerializeObject(paramObj, Formatting.None); + + var requestContent = new StringContent( + requestInput, + Encoding.UTF8, + MediaTypeNames.Application.Json); + + var client = _httpClientFactory.CreateClient(AelfClientConstant.SideChainClient); + + var response = await client.PostAsync(url, requestContent); + var content = await response.Content.ReadAsStringAsync(); + + if (!ResponseSuccess(response.StatusCode)) + { + _logger.LogError( + "[ContractClientError] PostError Response not success, url:{url}, code:{code}, message: {message}, params:{param}", + url, response.StatusCode, content, JsonConvert.SerializeObject(paramObj)); + + throw new UserFriendlyException(content, ((int)response.StatusCode).ToString()); + } + + _logger.LogInformation("[SideChainContractClient] PostAsync end:{url}", url); + return JsonConvert.DeserializeObject(content); + } + + public async Task PostAsync(string url, object paramObj) + { + _logger.LogInformation("[SideChainContractClient] PostAsync begin:{url}", url); + var requestInput = paramObj == null ? string.Empty : JsonConvert.SerializeObject(paramObj, Formatting.None); + + var requestContent = new StringContent( + requestInput, + Encoding.UTF8, + MediaTypeNames.Application.Json); + + var client = _httpClientFactory.CreateClient(AelfClientConstant.SideChainClient); + + var response = await client.PostAsync(url, requestContent); + var content = await response.Content.ReadAsStringAsync(); + + if (!ResponseSuccess(response.StatusCode)) + { + _logger.LogError( + "[ContractClientError] PostError Response not success, url:{url}, code:{code}, message: {message}, params:{param}", + url, response.StatusCode, content, JsonConvert.SerializeObject(paramObj)); + + throw new UserFriendlyException(content, ((int)response.StatusCode).ToString()); + } + + _logger.LogInformation("[SideChainContractClient] PostAsync end:{url}", url); + return content; + } + + private bool ResponseSuccess(HttpStatusCode statusCode) => + statusCode is HttpStatusCode.OK or HttpStatusCode.NoContent; +} \ No newline at end of file diff --git a/src/CAServer.Application/ContractService/ContractService.cs b/src/CAServer.Application/ContractService/ContractService.cs index c950fe56d..ba31c494e 100644 --- a/src/CAServer.Application/ContractService/ContractService.cs +++ b/src/CAServer.Application/ContractService/ContractService.cs @@ -7,6 +7,8 @@ using AElf.Types; using CAServer.CAAccount; using CAServer.CAAccount.Dtos; +using CAServer.Common; +using CAServer.Common.AelfClient; using CAServer.Commons; using CAServer.Grains.Grain.ApplicationHandler; using CAServer.Grains.State.ApplicationHandler; @@ -36,10 +38,11 @@ public class ContractService : IContractService, ISingletonDependency private readonly ISignatureProvider _signatureProvider; private readonly IIndicatorScope _indicatorScope; private readonly IDistributedEventBus _distributedEventBus; + private readonly IContractClientSelector _contractClientSelector; public ContractService(IOptions chainOptions, IOptions contractGrainOptions, IObjectMapper objectMapper, ISignatureProvider signatureProvider, ILogger logger, - IIndicatorScope indicatorScope, IDistributedEventBus distributedEventBus) + IIndicatorScope indicatorScope, IDistributedEventBus distributedEventBus, IContractClientSelector contractClientSelector) { _objectMapper = objectMapper; _logger = logger; @@ -48,6 +51,7 @@ public ContractService(IOptions chainOptions, IOptions SendTransactionToChainAsync(string chainId, IMessage param, @@ -60,9 +64,11 @@ private async Task SendTransactionToChainAsync(string chainI return null; } - var client = new AElfClient(chainInfo.BaseUrl); - await client.IsConnectedAsync(); - var ownAddress = client.GetAddressFromPubKey(chainInfo.PublicKey); + //var client = new AElfClient(chainInfo.BaseUrl); + var client = _contractClientSelector.GetContractClient(chainId); + //var ownAddress = client.GetAddressFromPubKey(chainInfo.PublicKey); + var ownAddress = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(chainInfo.PublicKey)) + .ToBase58(); _logger.LogDebug("Get Address From PubKey, ownAddress:{ownAddress}, ContractAddress: {ContractAddress} ", ownAddress, chainInfo.ContractAddress); var interIndicator = _indicatorScope.Begin(MonitorTag.AelfClient, @@ -117,6 +123,7 @@ await client.GenerateTransactionAsync(ownAddress, chainInfo.ContractAddress, met _indicatorScope.End(retryGetIndicator); } + return new TransactionInfoDto { Transaction = transaction, @@ -150,7 +157,7 @@ private async Task ForwardTransactionToChainAsync(string cha await Task.Delay(_contractServiceOptions.Delay); var transactionResult = await client.GetTransactionResultAsync(result.TransactionId); - + var times = 0; while ((transactionResult.Status == TransactionState.Pending || transactionResult.Status == TransactionState.NotExisted) && @@ -160,7 +167,7 @@ private async Task ForwardTransactionToChainAsync(string cha await Task.Delay(_contractServiceOptions.CryptoBoxRetryDelay); transactionResult = await client.GetTransactionResultAsync(result.TransactionId); } - + return new TransactionInfoDto { TransactionResultDto = transactionResult @@ -401,7 +408,7 @@ await client.GenerateTransactionAsync(ownAddress, redPackageContractAddress, met var transactionResult = await client.GetTransactionResultAsync(result.TransactionId); _logger.LogInformation("SendTransferRedPacketToChainAsync transactionResult: {transactionResult}", JsonConvert.SerializeObject(transactionResult)); - + var times = 0; while ((transactionResult.Status == TransactionState.Pending || transactionResult.Status == TransactionState.NotExisted) && diff --git a/src/CAServer.ContractEventHandler.Core/Application/IContractProvider.cs b/src/CAServer.ContractEventHandler.Core/Application/IContractProvider.cs index 4e39a2dd9..07223c263 100644 --- a/src/CAServer.ContractEventHandler.Core/Application/IContractProvider.cs +++ b/src/CAServer.ContractEventHandler.Core/Application/IContractProvider.cs @@ -7,6 +7,7 @@ using AElf.Client.Service; using AElf.Types; using CAServer.CAAccount.Dtos; +using CAServer.Common.AelfClient; using CAServer.Grains.Grain; using CAServer.Commons; using CAServer.ContractService; @@ -86,12 +87,14 @@ public class ContractProvider : IContractProvider private readonly IDistributedCache _distributedCache; private readonly BlockInfoOptions _blockInfoOptions; private readonly ContractServiceProxy _contractServiceProxy; + private readonly IContractClientSelector _contractClientSelector; public ContractProvider(ILogger logger, IOptionsSnapshot chainOptions, IOptionsSnapshot indexOptions, IClusterClient clusterClient, ISignatureProvider signatureProvider, IGraphQLProvider graphQlProvider, IIndicatorScope indicatorScope, IDistributedCache distributedCache, - IOptionsSnapshot blockInfoOptions, ContractServiceProxy contractServiceProxy) + IOptionsSnapshot blockInfoOptions, ContractServiceProxy contractServiceProxy, + IContractClientSelector contractClientSelector) { _logger = logger; _chainOptions = chainOptions.Value; @@ -102,6 +105,7 @@ public ContractProvider(ILogger logger, IOptionsSnapshot CallTransactionAsync(string chainId, string methodName, { var chainInfo = _chainOptions.ChainInfos[chainId]; - var client = new AElfClient(chainInfo.BaseUrl); - await client.IsConnectedAsync(); - var ownAddress = client.GetAddressFromPubKey(chainInfo.PublicKey); + //var client = new AElfClient(chainInfo.BaseUrl); + var client = _contractClientSelector.GetContractClient(chainId); + var ownAddress = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(chainInfo.PublicKey)) + .ToBase58(); var contractAddress = isCrossChain ? chainInfo.CrossChainContractAddress : chainInfo.ContractAddress; var generateIndicator = _indicatorScope.Begin(MonitorTag.AelfClient, @@ -302,7 +307,8 @@ public async Task CreateHolderInfoAsync(CreateHolderDto cr } catch (Exception e) { - _logger.LogError(e, "CreateHolderInfo error: {message}", JsonConvert.SerializeObject(createHolderDto.ToString())); + _logger.LogError(e, "CreateHolderInfo error: {message}", + JsonConvert.SerializeObject(createHolderDto.ToString())); return new TransactionResultDto { Status = TransactionState.Failed, @@ -343,7 +349,8 @@ public async Task CreateHolderInfoOnNonCreateChainAsync(Ch createHolderDto.CaHash = outputGetHolderInfo.CaHash; createHolderDto.ChainId = createChainId; - var result = await _contractServiceProxy.CreateHolderInfoOnNonCreateChainAsync(chainInfo.ChainId, createHolderDto); + var result = + await _contractServiceProxy.CreateHolderInfoOnNonCreateChainAsync(chainInfo.ChainId, createHolderDto); _logger.LogInformation( "accelerated registration on chain: {id} result: TransactionId: {transactionId}, BlockNumber: {number}, Status: {status}, ErrorInfo: {error}", @@ -371,10 +378,10 @@ public async Task SocialRecoveryAsync(SocialRecoveryDto so if (result != null) { _logger.LogInformation( - "SocialRecovery to chain: {id} result:" + - "TransactionId: {transactionId}, BlockNumber: {number}, Status: {status}, ErrorInfo: {error}", - socialRecoveryDto.ChainId, - result.TransactionId, result.BlockNumber, result.Status, result.Error); + "SocialRecovery to chain: {id} result:" + + "TransactionId: {transactionId}, BlockNumber: {number}, Status: {status}, ErrorInfo: {error}", + socialRecoveryDto.ChainId, + result.TransactionId, result.BlockNumber, result.Status, result.Error); } return result; @@ -396,8 +403,9 @@ public async Task ValidateTransactionAsync(string chainId, try { await CheckCreateChainIdAsync(result); - - var transactionDto = await _contractServiceProxy.ValidateTransactionAsync(chainId, result, unsetLoginGuardians); + + var transactionDto = + await _contractServiceProxy.ValidateTransactionAsync(chainId, result, unsetLoginGuardians); _logger.LogInformation( "ValidateTransaction to chain: {id} result:" + @@ -576,6 +584,7 @@ public async Task SendTransferRedPacketRefundAsync(RedPackag { return null; } + var grab = redPackageDetail.Items.Sum(item => long.Parse(item.Amount)); var sendInput = new RefundCryptoBoxInput { @@ -585,8 +594,9 @@ public async Task SendTransferRedPacketRefundAsync(RedPackag await redPackageKeyGrain.GenerateSignature( $"{redPackageId}-{long.Parse(redPackageDetail.TotalAmount) - grab}") }; - _logger.LogInformation("SendTransferRedPacketRefundAsync input {input}",JsonConvert.SerializeObject(sendInput)); - + _logger.LogInformation("SendTransferRedPacketRefundAsync input {input}", + JsonConvert.SerializeObject(sendInput)); + return await _contractServiceProxy.SendTransferRedPacketToChainAsync(chainId, sendInput, payRedPackageFrom, chainInfo.RedPackageContractAddress, MethodName.RefundCryptoBox); } @@ -627,7 +637,8 @@ await redPackageKeyGrain.GenerateSignature( CryptoBoxId = redPackageId.ToString(), TransferCryptoBoxInputs = { list } }; - _logger.LogInformation("SendTransferRedPacketToChainAsync sendInput: {sendInput}", JsonConvert.SerializeObject(sendInput)); + _logger.LogInformation("SendTransferRedPacketToChainAsync sendInput: {sendInput}", + JsonConvert.SerializeObject(sendInput)); var contractServiceGrain = _clusterClient.GetGrain(Guid.NewGuid()); return await _contractServiceProxy.SendTransferRedPacketToChainAsync(chainId, sendInput, payRedPackageFrom, diff --git a/src/CAServer.ContractEventHandler.Core/CAServerContractEventHandlerCoreModule.cs b/src/CAServer.ContractEventHandler.Core/CAServerContractEventHandlerCoreModule.cs index 1af628415..62547a3b9 100644 --- a/src/CAServer.ContractEventHandler.Core/CAServerContractEventHandlerCoreModule.cs +++ b/src/CAServer.ContractEventHandler.Core/CAServerContractEventHandlerCoreModule.cs @@ -1,9 +1,13 @@ +using System; +using System.Collections.Generic; +using CAServer.Commons; using CAServer.ContractEventHandler.Core.Application; using CAServer.Grains.Grain.ValidateOriginChainId; using CAServer.Signature; using GraphQL.Client.Abstractions; using GraphQL.Client.Http; using GraphQL.Client.Serializer.Newtonsoft; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Volo.Abp; using Volo.Abp.AutoMapper; @@ -34,6 +38,31 @@ public override void ConfigureServices(ServiceConfigurationContext context) context.Services.AddSingleton(new GraphQLHttpClient(configuration["GraphQL:Configuration"], new NewtonsoftJsonSerializer())); context.Services.AddScoped(sp => sp.GetRequiredService()); + + AddAelfClient(context, configuration); + } + + private void AddAelfClient(ServiceConfigurationContext context, IConfiguration configuration) + { + var chainInfos = configuration.GetValue("Chains"); + if (chainInfos == null || chainInfos.ChainInfos.IsNullOrEmpty()) + { + return; + } + + foreach (var chainInfo in chainInfos.ChainInfos) + { + var clientName = chainInfo.Key == CommonConstant.MainChainId + ? AelfClientConstant.MainChainClient + : AelfClientConstant.SideChainClient; + + context.Services.AddHttpClient(clientName, + httpClient => + { + httpClient.BaseAddress = new Uri(chainInfo.Value.BaseUrl); + httpClient.Timeout = TimeSpan.FromSeconds(60); + }); + } } public override void OnPostApplicationInitialization(ApplicationInitializationContext context) From e9fb0ac4cc3493eac1e6a07e9fff65549135257c Mon Sep 17 00:00:00 2001 From: felix-zhaolei Date: Wed, 18 Dec 2024 12:41:41 +0800 Subject: [PATCH 2/2] modify: add method. --- .../Common/AelfClient/IContractClient.cs | 6 ++---- .../Common/AelfClient/MainChainContractClient.cs | 13 ++++++++++++- .../Common/AelfClient/SideChainContractClient.cs | 11 +++++++++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/CAServer.Application/Common/AelfClient/IContractClient.cs b/src/CAServer.Application/Common/AelfClient/IContractClient.cs index b87d627fc..4b1f028b1 100644 --- a/src/CAServer.Application/Common/AelfClient/IContractClient.cs +++ b/src/CAServer.Application/Common/AelfClient/IContractClient.cs @@ -5,10 +5,6 @@ using AElf.Client.Dto; using AElf.Types; using Google.Protobuf; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using ChainOptions = CAServer.Options.ChainOptions; namespace CAServer.Common.AelfClient; @@ -26,5 +22,7 @@ Task GenerateTransactionAsync( Task GetTransactionResultAsync(string transactionId); Task ExecuteTransactionAsync(ExecuteTransactionDto input); + + Transaction SignTransaction(string privateKeyHex, Transaction transaction); } diff --git a/src/CAServer.Application/Common/AelfClient/MainChainContractClient.cs b/src/CAServer.Application/Common/AelfClient/MainChainContractClient.cs index bece00d68..2fb45a3b2 100644 --- a/src/CAServer.Application/Common/AelfClient/MainChainContractClient.cs +++ b/src/CAServer.Application/Common/AelfClient/MainChainContractClient.cs @@ -6,7 +6,9 @@ using System.Net.Mime; using System.Text; using System.Threading.Tasks; +using AElf; using AElf.Client.Dto; +using AElf.Cryptography; using AElf.Types; using CAServer.Commons; using Google.Protobuf; @@ -93,10 +95,19 @@ public async Task ExecuteTransactionAsync(ExecuteTransactionDto input) input.RawTransaction } }; - var res = await PostAsync(url,param); + var res = await PostAsync(url, param); return res; } + public Transaction SignTransaction(string privateKeyHex, Transaction transaction) + { + byte[] byteArray = transaction.GetHash().ToByteArray(); + byte[] numArray = + CryptoHelper.SignWithPrivateKey(ByteArrayHelper.HexStringToByteArray(privateKeyHex), byteArray); + transaction.Signature = ByteString.CopyFrom(numArray); + return transaction; + } + public async Task GetChainStatusAsync() { var uri = "api/blockChain/chainStatus"; diff --git a/src/CAServer.Application/Common/AelfClient/SideChainContractClient.cs b/src/CAServer.Application/Common/AelfClient/SideChainContractClient.cs index d0d580dd3..25a4e4fc7 100644 --- a/src/CAServer.Application/Common/AelfClient/SideChainContractClient.cs +++ b/src/CAServer.Application/Common/AelfClient/SideChainContractClient.cs @@ -6,7 +6,9 @@ using System.Net.Mime; using System.Text; using System.Threading.Tasks; +using AElf; using AElf.Client.Dto; +using AElf.Cryptography; using AElf.Types; using CAServer.Commons; using Google.Protobuf; @@ -96,6 +98,15 @@ public async Task ExecuteTransactionAsync(ExecuteTransactionDto input) var res = await PostAsync(url, param); return res; } + + public Transaction SignTransaction(string privateKeyHex, Transaction transaction) + { + byte[] byteArray = transaction.GetHash().ToByteArray(); + byte[] numArray = + CryptoHelper.SignWithPrivateKey(ByteArrayHelper.HexStringToByteArray(privateKeyHex), byteArray); + transaction.Signature = ByteString.CopyFrom(numArray); + return transaction; + } public async Task GetChainStatusAsync() {