public async Task <List <ChatMessageDto> > SeekHistory(string channel, string dateStart, string dateEnd) { List <ChatMessage> messagesData = new List <ChatMessage>(); List <ChatMessageDto> result = new List <ChatMessageDto>(); try { DateTime start = DateTime.ParseExact(dateStart, "ddMMyyyyHH:mm:ss", CultureInfo.InvariantCulture); DateTime end = DateTime.ParseExact(dateEnd, "ddMMyyyyHH:mm:ss", CultureInfo.InvariantCulture); messagesData = await _chatRepository.SeekHistoryMessage(channel, start, end); } catch (ArgumentNullException argumentEx) { throw HttpHelper.HttpError(System.Net.HttpStatusCode.BadRequest, "Some argument are null"); } catch (FormatException formatEx) { throw HttpHelper.HttpError(System.Net.HttpStatusCode.BadRequest, "Date format not supported"); } catch (Exception ex) { _logger.Log(LogLevel.Error, _logCategory, "An error occured when seek history in chat repository", ex.Message); throw HttpHelper.HttpError(System.Net.HttpStatusCode.InternalServerError, "Server Internal error(s)"); } if (result.Count == 0) { throw HttpHelper.HttpError(System.Net.HttpStatusCode.NoContent, $"No data found in request date range DateStart={dateStart}, DateEnd={dateEnd}"); } else { foreach (ChatMessage msg in messagesData) { var message = new ChatMessageDto { Message = msg.Message, TimeStamp = TimestampHelper.DateTimeToUnixTimeStamp(msg.Date), UserInfo = new ChatUserInfoDto { UserId = msg.UserInfo.UserId, Data = msg.UserInfo.Data.ToString(), } }; result.Add(message); } return(result); } }
public async Task LoadHistory(RequestContext <IScenePeerClient> ctx) { List <ChatMessageDto> result = new List <ChatMessageDto>(); try { long startTimestamp = ctx.ReadObject <long>(); long endTimestamp = ctx.ReadObject <long>(); DateTime start = TimestampHelper.UnixTimeStampSecondToDateTime(startTimestamp); DateTime end = TimestampHelper.UnixTimeStampSecondToDateTime(endTimestamp); string channelName = ctx.RemotePeer.SceneId; var messagesData = await _chat.LoadHistory(channelName, start, end); foreach (ChatMessage msg in messagesData) { var message = new ChatMessageDto { Message = msg.Message, TimeStamp = TimestampHelper.DateTimeToUnixTimeStamp(msg.Date), UserInfo = new ChatUserInfoDto { UserId = msg.UserInfo.UserId, Data = msg.UserInfo.Data.ToString(), } }; result.Add(message); } } catch (Exception ex) { _logger.Log(LogLevel.Error, _logCategory, "Error occured when server try to load history", ex); throw new ClientException(ex.Message); } ctx.SendValue(result); }
public static async Task <BeforePayoutResult> CanTryPayout(string nodeID, string offerId, string holdingAddress, string holdingStorageAddress, string litigationStorageAddress, string identity, int?blockchainID, string selectedAddress) { if (nodeID == null || offerId == null || holdingAddress == null || holdingStorageAddress == null || litigationStorageAddress == null || identity == null || blockchainID == null || selectedAddress == null) { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "Missing data in request." }); } await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { var holdingStorageAddressModel = await connection.QueryFirstOrDefaultAsync <ContractAddress>(ContractsSql.GetHoldingStorageAddressByAddress, new { holdingStorageAddress = holdingStorageAddress, blockchainID }); holdingStorageAddress = holdingStorageAddressModel?.Address; if (holdingStorageAddress == null) { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "OT Hub is not familiar with this holding storage smart contract address for this blockchain id " + blockchainID }); } var blockchainRow = await connection.QueryFirstAsync("SELECT * FROM blockchains where id = @id", new { id = blockchainID }); string blockchainName = blockchainRow.BlockchainName; string networkName = blockchainRow.NetworkName; string explorerTransactionUrl = blockchainRow.TransactionUrl; BlockchainType blockchainEnum = Enum.Parse <BlockchainType>(blockchainName); BlockchainNetwork networkNameEnum = Enum.Parse <BlockchainNetwork>(networkName); string nodeUrl = await connection.ExecuteScalarAsync <string>(@"SELECT BlockchainNodeUrl FROM blockchains WHERE id = @id", new { id = blockchainID }); var cl = new Web3(nodeUrl); var eth = new EthApiService(cl.Client); var ercContract = new Contract(eth, AbiHelper.GetContractAbi(ContractTypeEnum.ERC725, blockchainEnum, networkNameEnum), identity); Function keyHasPurposeFunction = ercContract.GetFunction("keyHasPurpose"); var abiEncode = new ABIEncode(); byte[] test = abiEncode.GetABIEncodedPacked(selectedAddress.HexToByteArray()); byte[] bytes = CalculateHash(test); bool hasPermission = await keyHasPurposeFunction.CallAsync <bool>(bytes, 1) || await keyHasPurposeFunction.CallAsync <bool>(bytes, 2); if (!hasPermission) { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "The address you have selected in MetaMask (" + selectedAddress + ") does not have permission to payout on the identity " + identity + ". You need to pick either your management wallet or operational wallet." }); } var holdingStorageAbi = AbiHelper.GetContractAbi(ContractTypeEnum.HoldingStorage, blockchainEnum, networkNameEnum); holdingAddress = (await connection.QueryFirstOrDefaultAsync <ContractAddress>(ContractsSql.GetHoldingAddressByAddress, new { holdingAddress = holdingAddress, blockchainID }))?.Address; if (holdingAddress == null) { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "OT Hub is not familiar with this holding smart contract address for this blockchain id " + blockchainID }); } var offerIdArray = offerId.HexToByteArray(); var holdingStorageContract = new Contract(new EthApiService(cl.Client), holdingStorageAbi, holdingStorageAddress); var getHolderStakedAmountFunction = holdingStorageContract.GetFunction("getHolderStakedAmount"); var holderStakedAmount = await getHolderStakedAmountFunction.CallAsync <BigInteger>(offerIdArray, identity); var getHolderPaymentTimestampFunction = holdingStorageContract.GetFunction("getHolderPaymentTimestamp"); var holderPaymentTimestamp = await getHolderPaymentTimestampFunction.CallAsync <BigInteger>(offerIdArray, identity); var getOfferHoldingTimeInMinutesFunction = holdingStorageContract.GetFunction("getOfferHoldingTimeInMinutes"); var offerHoldingTimeInMinutes = await getOfferHoldingTimeInMinutesFunction.CallAsync <BigInteger>(offerIdArray); var getHolderPaidAmountFunction = holdingStorageContract.GetFunction("getHolderPaidAmount"); var holderPaidAmount = await getHolderPaidAmountFunction.CallAsync <BigInteger>(offerIdArray, identity); if (holderStakedAmount <= 0) { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "The smart contract says this identity did not hold data for this job. The transaction will likely fail if you try to send this manually." }); } //long holdingTime = await connection.ExecuteScalarAsync<long>( // @"select HoldingTimeInMinutes from otoffer where OfferID = @offerID and blockchainID = @blockchainID", // new // { // offerId, // blockchainID // }); var latestBlockParam = BlockParameter.CreateLatest(); var block = await cl.Eth.Blocks.GetBlockWithTransactionsByNumber.SendRequestAsync(latestBlockParam); DateTime blockDate = TimestampHelper.UnixTimeStampToDateTime((double)block.Timestamp.Value); DateTime jobStartDate = await connection.ExecuteScalarAsync <DateTime>(@"SELECT Timestamp FROM otcontract_holding_offerfinalized where OfferID = @offerID and BlockchainID = @blockchainID", new { offerID = offerId, blockchainID }); DateTime jobEndDate = jobStartDate.AddMinutes((int)offerHoldingTimeInMinutes); if (blockDate > jobEndDate) { blockDate = jobEndDate; } BigInteger blockTimestamp = new BigInteger(TimestampHelper.DateTimeToUnixTimeStamp(blockDate)); var amountToTransfer = holderStakedAmount; amountToTransfer = amountToTransfer * (blockTimestamp - holderPaymentTimestamp); amountToTransfer = amountToTransfer / (offerHoldingTimeInMinutes * 60); decimal friendlyEstimatedPayout = Web3.Convert.FromWei(amountToTransfer); if (holderPaidAmount == holderStakedAmount) { var friendlyAmount = Web3.Convert.FromWei(holderPaidAmount); return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "The smart contract says you have been paid " + friendlyAmount + " TRAC for this job. The transaction will likely fail if you try to send this manually." }); } if (!String.IsNullOrWhiteSpace(litigationStorageAddress)) { litigationStorageAddress = (await connection.QueryFirstOrDefaultAsync <ContractAddress>(@"select Address from otcontract where Type = 9 AND Address = @litigationStorageAddress AND blockchainID = @blockchainID", new { litigationStorageAddress = litigationStorageAddress, blockchainID }))?.Address; if (litigationStorageAddress == null) { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "OT Hub is not familiar with this litigation storage smart contract address for this blockchain id " + blockchainID }); } Contract storageContract = new Contract((EthApiService)cl.Eth, AbiHelper.GetContractAbi(ContractTypeEnum.LitigationStorage, blockchainEnum, networkNameEnum), litigationStorageAddress); Function getLitigationStatusFunction = storageContract.GetFunction("getLitigationStatus"); Function getLitigationTimestampFunction = storageContract.GetFunction("getLitigationTimestamp"); BigInteger litigationTimestampInt = await getLitigationTimestampFunction.CallAsync <BigInteger>(latestBlockParam, offerIdArray, identity); Function getOfferLitigationIntervalInMinutesFunction = holdingStorageContract.GetFunction("getOfferLitigationIntervalInMinutes"); BigInteger litgationInterval = await getOfferLitigationIntervalInMinutesFunction.CallAsync <BigInteger>(latestBlockParam, offerIdArray) * 60; var status = await getLitigationStatusFunction.CallAsync <UInt16>(latestBlockParam, offerIdArray, identity); if (status == 1) //initiated { if (litigationTimestampInt + (litgationInterval * 2) >= block.Timestamp.Value) { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "The smart contract says 'Unanswered litigation in progress, cannot pay out'. The transaction will likely fail if you try to send this manually." }); } } else if (status == 2) //answered { if (litigationTimestampInt + (litgationInterval) >= block.Timestamp.Value) { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "The smart contract says 'Unanswered litigation in progress, cannot pay out'. The transaction will likely fail if you try to send this manually." }); } } else if (status == 0) //completed { //Do nothing as this is fine } else { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "The smart contract says 'Data holder is replaced or being replaced, cannot payout!'. The transaction will likely fail if you try to send this manually." }); } } return(new BeforePayoutResult { CanTryPayout = true, BlockchainExplorerUrlFormat = explorerTransactionUrl, EstimatedPayout = friendlyEstimatedPayout }); } }