Skip to content

Commit

Permalink
Add TonGift activity. (#742)
Browse files Browse the repository at this point in the history
feat: add tongifts activity
  • Loading branch information
felix-zhaolei authored Aug 20, 2024
1 parent 439bcd4 commit e0e86b8
Show file tree
Hide file tree
Showing 12 changed files with 308 additions and 3 deletions.
22 changes: 22 additions & 0 deletions src/CAServer.Application.Contracts/Commons/HMACSHA256Helper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using System.Security.Cryptography;
using System.Text;

namespace CAServer.Commons;

public class HMACSHA256Helper
{

public static string ComputeHash(string data, string key)
{
var encoding = new UTF8Encoding();
byte[] keyBytes = encoding.GetBytes(key);
byte[] messageBytes = encoding.GetBytes(data);
using (var hmacsha256 = new HMACSHA256(keyBytes))
{
byte[] hashBytes = hmacsha256.ComputeHash(messageBytes);
return Convert.ToBase64String(hashBytes);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Collections.Generic;
using Newtonsoft.Json;

namespace CAServer.Growth.Dtos;

public class TonGiftsRequestDto
{

[JsonProperty("status")]
public string Status { get; set; }

[JsonProperty("userIds")]
public List<string> UserIds { get; set; }

[JsonProperty("taskId")]
public string TaskId { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Collections.Generic;

namespace CAServer.Growth.Dtos;

public class TonGiftsResponseDto
{
public List<SuccessfulUpdate> SuccessfulUpdates { get; set; }

public List<FailedUpdate> FailedUpdates { get; set; }
}

public class SuccessfulUpdate : TonGiftsBase
{
}

public class FailedUpdate : TonGiftsBase
{
public string Error { get; set; }
}

public class TonGiftsBase
{
public string UserId { get; set; }
public string TaskId { get; set; }
public string Status { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace CAServer.Growth.Dtos;

public class ValidateHamsterScoreResponseDto
{
public Result Result { get; set; }

public ErrorMsg ErrorMsg { get; set; }
}


public class ErrorMsg
{
public string Message { get; set; }
}

public class Result
{
public bool ValidateResult { get; set; } = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,9 @@ public interface IGrowthStatisticAppService
Task<RewardProgressResponseDto> GetRewardProgressAsync(ActivityEnums activityEnum);
Task<BeInvitedConfigResponseDto> GetBeInvitedConfigAsync();
Task<ActivityBaseInfoDto> ActivityBaseInfoAsync();

Task<ValidateHamsterScoreResponseDto> ValidateHamsterScoreAsync(string userId);
Task RepairHamsterDataAsync();
Task CollectHamsterUserIdsAsync(string userId);
Task TonGiftsValidateAsync();
}
16 changes: 16 additions & 0 deletions src/CAServer.Application/CAActivity/Provider/ActivityProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,20 @@ public async Task<CaHolderTransactionIndex> GetNotSuccessTransactionAsync(string
QueryContainer Filter(QueryContainerDescriptor<CaHolderTransactionIndex> f) => f.Bool(b => b.Must(mustQuery));
return await _transactionRepository.GetAsync(Filter);
}

public async Task<GuardiansDto> GetCaHolderInfoAsync(string loginGuardianIdentifierHash, int skipCount = 0, int maxResultCount = 10)
{
return await _graphQlHelper.QueryAsync<GuardiansDto>(new GraphQLRequest
{
Query = @"
query(loginGuardianIdentifierHash:[String],$skipCount:Int!,$maxResultCount:Int!) {
caHolderInfo(dto: {loginGuardianIdentifierHash:loginGuardianIdentifierHash,skipCount:$skipCount,maxResultCount:$maxResultCount}){
id,chainId,caHash,caAddress,originChainId,managerInfos{address,extraData},guardianList{guardians{verifierId,identifierHash,salt,isLoginGuardian,type}}}
}",
Variables = new
{
loginGuardianIdentifierHash , skipCount, maxResultCount
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,7 @@ Task<List<CaHolderTransactionIndex>> GetNotSuccessTransactionsAsync(string caAdd
long endBlockHeight);

Task<CaHolderTransactionIndex> GetNotSuccessTransactionAsync(string caAddress, string transactionId);

Task<GuardiansDto> GetCaHolderInfoAsync(string identifierHash, int skipCount = 0,
int maxResultCount = 10);
}
149 changes: 146 additions & 3 deletions src/CAServer.Application/Growth/GrowthStatisticAppService.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Mime;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using AElf;
using AElf.Indexing.Elasticsearch;
using CAServer.CAActivity.Provider;
using CAServer.Cache;
using CAServer.Common;
using CAServer.Commons;
using CAServer.Entities.Es;
using CAServer.EnumType;
using CAServer.Grains;
using CAServer.Grains.Grain.ApplicationHandler;
using CAServer.Grains.Grain.Guardian;
using CAServer.Growth.Dtos;
using CAServer.Growth.Provider;
using CAServer.Options;
Expand All @@ -18,10 +25,12 @@
using Microsoft.Extensions.Options;
using Nest;
using Newtonsoft.Json;
using Orleans;
using Volo.Abp;
using Volo.Abp.Auditing;
using Volo.Abp.Authorization;
using Volo.Abp.Users;
using Result = CAServer.Growth.Dtos.Result;

namespace CAServer.Growth;

Expand All @@ -41,6 +50,10 @@ public class GrowthStatisticAppService : CAServerAppService, IGrowthStatisticApp
private readonly HamsterOptions _hamsterOptions;
private readonly BeInvitedConfigOptions _beInvitedConfigOptions;
private const string RepairDataCache = "Hamster:DataRepairKey";
private const string HamsterTonGiftsUserIdsKey = "Hamster:TonGifts:UserIdsKey";
private readonly IClusterClient _clusterClient;
private readonly IHttpClientFactory _httpClientFactory;
private readonly TonGiftsOptions _tonGiftsOptions;


public GrowthStatisticAppService(IGrowthProvider growthProvider,
Expand All @@ -49,14 +62,18 @@ public GrowthStatisticAppService(IGrowthProvider growthProvider,
IActivityProvider activityProvider, ILogger<GrowthStatisticAppService> logger,
IUserAssetsProvider userAssetsProvider, IOptionsSnapshot<ActivityConfigOptions> activityConfigOptions,
IOptionsSnapshot<HamsterOptions> hamsterOptions,
IOptionsSnapshot<BeInvitedConfigOptions> beInvitedConfigOptions)
IOptionsSnapshot<BeInvitedConfigOptions> beInvitedConfigOptions, IClusterClient clusterClient,
IHttpClientFactory httpClientFactory, IOptionsSnapshot<TonGiftsOptions> tonGiftsOptions)
{
_growthProvider = growthProvider;
_caHolderRepository = caHolderRepository;
_cacheProvider = cacheProvider;
_activityProvider = activityProvider;
_logger = logger;
_userAssetsProvider = userAssetsProvider;
_clusterClient = clusterClient;
_httpClientFactory = httpClientFactory;
_tonGiftsOptions = tonGiftsOptions.Value;
_beInvitedConfigOptions = beInvitedConfigOptions.Value;
_hamsterOptions = hamsterOptions.Value;
_activityConfigOptions = activityConfigOptions.Value;
Expand Down Expand Up @@ -447,6 +464,7 @@ await _growthProvider.GetReferralRecordListAsync(null, null, 0, Int16.MaxValue,
{
result.AddRange(scoreResult);
}

index += length;
}
}
Expand Down Expand Up @@ -645,6 +663,72 @@ public async Task<ActivityBaseInfoDto> ActivityBaseInfoAsync()
};
}

public async Task<ValidateHamsterScoreResponseDto> ValidateHamsterScoreAsync(string userId)
{
var guardianGrainId = GrainIdHelper.GenerateGrainId("Guardian", userId);
var guardianGrain = _clusterClient.GetGrain<IGuardianGrain>(guardianGrainId);
var guardian = guardianGrain.GetGuardianAsync(userId).Result;
if (!guardian.Message.IsNullOrEmpty())
{
return new ValidateHamsterScoreResponseDto
{
Result = new Result
{
ValidateResult = false
},
ErrorMsg =
{
Message = guardian.Message
}
};
}

var identifierHash = guardian.Data.IdentifierHash;
var caHolderInfo =
await _activityProvider.GetCaHolderInfoAsync(identifierHash);
if (caHolderInfo == null || caHolderInfo.CaHolderInfo.Count == 0)
{
return new ValidateHamsterScoreResponseDto()
{
Result =
{
ValidateResult = false
},
ErrorMsg =
{
Message = "Account not exist."
}
};
}

var address = caHolderInfo.CaHolderInfo.FirstOrDefault()?.CaAddress;
var hamsterScoreList =
await _growthProvider.GetHamsterScoreListAsync(new List<string> { address }, DateTime.UtcNow.AddDays(-1),
DateTime.UtcNow);
if (hamsterScoreList == null || hamsterScoreList.GetScoreInfos.Count == 0)
{
return new ValidateHamsterScoreResponseDto()
{
Result = new Result
{
ValidateResult = false
},
ErrorMsg = new ErrorMsg
{
Message = "Validate failed."
}
};
}

return new ValidateHamsterScoreResponseDto
{
Result = new Result
{
ValidateResult = true
}
};
}

private ActivityConfig GetActivityDetails(ActivityEnums activityEnum)
{
_activityConfigOptions.ActivityConfigMap.TryGetValue(activityEnum.ToString(), out var config);
Expand Down Expand Up @@ -673,10 +757,8 @@ public async Task RepairHamsterDataAsync()
_logger.LogDebug("No data need to be repaired.");
return;
}
_logger.LogDebug("Total Count is {count}",repairList.Count);

_logger.LogDebug("Total Count is {count}", repairList.Count);

var count = 0;
foreach (var repair in repairList)
{
Expand Down Expand Up @@ -716,6 +798,67 @@ await _activityProvider.GetCaHolderInfoAsync(new List<string>(),
}
}

public async Task CollectHamsterUserIdsAsync(string userId)
{
var expire = TimeSpan.FromDays(30);
await _cacheProvider.SetAddAsync(HamsterTonGiftsUserIdsKey, userId, expire);
}

public async Task TonGiftsValidateAsync()
{
var userIds = await _cacheProvider.SetMembersAsync(HamsterTonGiftsUserIdsKey);
if (userIds.Length == 0)
{
_logger.LogDebug("No users need to be validate.");
return;
}

var ids = new List<string>();
foreach (var id in userIds)
{
var guardianGrainId = GrainIdHelper.GenerateGrainId("Guardian", id);
var guardianGrain = _clusterClient.GetGrain<IGuardianGrain>(guardianGrainId);
var guardian = guardianGrain.GetGuardianAsync(id).Result;
if (!guardian.Message.IsNullOrEmpty())
{
_logger.LogDebug("TonGift validate error : query user from grain error:{error}", guardian.Message);
continue;
}

var identifierHash = guardian.Data.IdentifierHash;
var caHolderInfo =
await _activityProvider.GetCaHolderInfoAsync(identifierHash);
if (caHolderInfo == null || caHolderInfo.CaHolderInfo.Count == 0)
{
_logger.LogDebug("TonGift validate error : query user from graphQl error: user not exists");
continue;
}

ids.Add(id);
}

var param = new TonGiftsRequestDto()
{
TaskId = _tonGiftsOptions.TaskId,
Status = "completed",
UserIds = ids
};
var rawStr = JsonConvert.SerializeObject(param);
var t = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds().ToString();
var Hash = HMACSHA256Helper.ComputeHash("rawStr=" + param + "&t=" + t, _tonGiftsOptions.ApiKey);
var apiKey = _tonGiftsOptions.ApiKey;
const string url = "https://devmini.tongifts.app/";
var client = _httpClientFactory.CreateClient();
var tokenParam = JsonConvert.SerializeObject(new
{ rawStr, apiKey, Hash, t });
var requestParam = new StringContent(tokenParam,
Encoding.UTF8,
MediaTypeNames.Application.Json);

var response = await client.PostAsync(url, requestParam);
var result = await response.Content.ReadAsStringAsync();
}

private async Task<Dictionary<string, CAHolderIndex>> GetNickNameByCaHashes(List<string> caHashes)
{
var caHolderList = await GetCaHolderByCaHashAsync(caHashes);
Expand Down
11 changes: 11 additions & 0 deletions src/CAServer.Application/Options/TonGiftsOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Collections.Generic;

namespace CAServer.Options;

public class TonGiftsOptions
{
public string ApiKey { get; set; }


public string TaskId { get; set; }
}
1 change: 1 addition & 0 deletions src/CAServer.Application/Verifier/VerifierAppService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ public async Task<VerificationCodeResponse> VerifyTelegramTokenAsync(VerifyToken
try
{
var userId = GetTelegramUserId(requestDto.AccessToken);
_logger.LogDebug("TeleGram userid is {uid}",userId);
var hashInfo = await GetSaltAndHashAsync(userId);
var response =
await _verifierServerClient.VerifyTelegramTokenAsync(requestDto, hashInfo.Item1, hashInfo.Item2);
Expand Down
Loading

0 comments on commit e0e86b8

Please sign in to comment.