Ejemplo n.º 1
0
        private async Task AggregateRequests(string clientId, string asset, OffchainTransferType type)
        {
            var list = (await _offchainRequestRepository.GetRequestsForClient(clientId)).Where(x => x.AssetId == asset && x.TransferType == type).ToList();

            var masterRequest = list.FirstOrDefault(x =>
                                                    (x.StartProcessing == null || (DateTime.UtcNow - x.StartProcessing.Value).TotalMinutes > 5) && x.ServerLock == null);

            if (masterRequest == null)
            {
                return;
            }

            await _offchainRequestRepository.DeleteRequest(masterRequest.RequestId);

            LogToFile(masterRequest.ToJson());

            var masterTransfer = await _offchainTransferRepository.GetTransfer(masterRequest.TransferId);

            int count = 0;

            while (count < 50)
            {
                list = (await _offchainRequestRepository.GetRequestsForClient(clientId))
                       .Where(x => (x.StartProcessing == null || (DateTime.UtcNow - x.StartProcessing.Value).TotalMinutes > 5) && x.ServerLock == null)
                       .Where(x => x.AssetId == asset && x.RequestId != masterRequest.RequestId && x.TransferType == type).ToList();
                if (list.Count < 1)
                {
                    break;
                }

                var current = list.FirstOrDefault();

                await _offchainRequestRepository.DeleteRequest(current.RequestId);

                LogToFile(current.ToJson());

                var currentTransfer = await _offchainTransferRepository.GetTransfer(current.TransferId);

                await _offchainTransferRepository.SetTransferIsChild(currentTransfer.Id, masterTransfer.Id);

                await _offchainTransferRepository.AddChildTransfer(masterTransfer.Id, currentTransfer);

                count++;
            }

            await _offchainRequestRepository.CreateRequest(masterTransfer.Id, masterTransfer.ClientId,
                                                           masterTransfer.AssetId, masterRequest.Type, masterTransfer.Type);
        }
        private async Task CreateHubCashoutIfNeed(IOffchainTransfer offchainTransfer)
        {
            try
            {
                var client = await _walletCredentialsRepository.GetAsync(offchainTransfer.ClientId);

                var currentRequests = (await _offchainRequestRepository.GetRequestsForClient(offchainTransfer.ClientId)).ToList();
                var currentChannels = await _bitcoinApiClient.Balances(client.MultiSig);

                var hasBtcRequest =
                    currentRequests.FirstOrDefault(x => x.AssetId == LykkeConstants.BitcoinAssetId &&
                                                   x.TransferType == OffchainTransferType.HubCashout) != null;
                var hasLkkRequest =
                    currentRequests.FirstOrDefault(x => x.AssetId == LykkeConstants.LykkeAssetId &&
                                                   x.TransferType == OffchainTransferType.HubCashout) != null;

                var btcSetting = await GetAssetSetting(LykkeConstants.BitcoinAssetId);

                var lkkSetting = await GetAssetSetting(LykkeConstants.LykkeAssetId);

                var btcHubAmount = !currentChannels.HasError &&
                                   currentChannels.Balances.ContainsKey(LykkeConstants.BitcoinAssetId) &&
                                   currentChannels.Balances[LykkeConstants.BitcoinAssetId].Actual
                                    ? currentChannels.Balances[LykkeConstants.BitcoinAssetId].HubAmount
                                    : 0;

                var lkkHubAmount = !currentChannels.HasError &&
                                   currentChannels.Balances.ContainsKey(LykkeConstants.LykkeAssetId) &&
                                   currentChannels.Balances[LykkeConstants.LykkeAssetId].Actual
                                    ? currentChannels.Balances[LykkeConstants.LykkeAssetId].HubAmount
                                    : 0;

                var needBtcCashout = offchainTransfer.AssetId != LykkeConstants.BitcoinAssetId && btcHubAmount > btcSetting.Dust && !hasBtcRequest;
                var needLkkCashout = offchainTransfer.AssetId != LykkeConstants.LykkeAssetId && lkkHubAmount > lkkSetting.Dust && !hasLkkRequest;

                await _offchainRequestService.CreateHubCashoutRequests(offchainTransfer.ClientId, needBtcCashout?btcHubAmount : 0, needLkkCashout?lkkHubAmount : 0);
            }
            catch (Exception e)
            {
                await _log.WriteErrorAsync(nameof(OffchainTransactionFinalizeFunction), nameof(CreateHubCashoutIfNeed), $"{offchainTransfer.ClientId}", e);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Process offchain channel
        /// </summary>
        /// <returns></returns>
        //[HttpPost("finalizeRefLinkTransfer")] --reserved for version 2
        //[SwaggerOperation("FinalizeRefLinkTransfer")]
        //[ProducesResponseType(typeof(OffchainSuccessTradeRespModel), (int)HttpStatusCode.OK)]
        //[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
        //[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.NotFound)]
        private async Task <IActionResult> Finalize([FromBody] OffchainFinalizeModel request)
        {
            var clientId = request.ClientId;

            await CheckOffchain(clientId);

            if (string.IsNullOrEmpty(request.ClientRevokePubKey))
            {
                return(await LogAndReturnBadRequest(request, ControllerContext, "ClientRevokePubKey must not be empty"));
            }

            if (string.IsNullOrEmpty(request.SignedTransferTransaction))
            {
                return(await LogAndReturnBadRequest(request, ControllerContext, "SignedTransferTransaction must not be empty"));
            }

            if (string.IsNullOrEmpty(request.TransferId))
            {
                return(await LogAndReturnBadRequest(request, ControllerContext, "TransferId must not be empty"));
            }

            var refLinkEntity = await _referralLinksService.GetReferralLinkById(request.RefLinkId);

            if (refLinkEntity == null)
            {
                return(await LogAndReturnBadRequest(request, ControllerContext, "RefLinkId not found"));
            }

            try
            {
                var response = await _offchainService.Finalize(clientId, request.TransferId, request.ClientRevokePubKey, request.ClientRevokeEncryptedPrivateKey, request.SignedTransferTransaction);

                if (response == null)
                {
                    return(await LogAndReturnNotFound(request, ControllerContext, "OffchainService Finalize returned NULL. Can not finalize transfer."));
                }

                if (response.OperationResult == OffchainOperationResult.ClientCommitment)
                {
                    AttachSenderTransferToRefLink(refLinkEntity, response.TransferId);
                }
                else
                {
                    await LogWarn(request, ControllerContext, $"_offchainService.Finalize returned unexpected result :  {response.ToJson()}");
                }

                var offchainRequest =
                    (await _offchainRequestRepository.GetRequestsForClient(clientId)).FirstOrDefault(
                        x => x.TransferId == request.TransferId);

                if (offchainRequest != null)
                {
                    await _offchainRequestRepository.Complete(offchainRequest.RequestId);
                    await LogInfo(request, ControllerContext, $"Offchain request set to complete: {offchainRequest.ToJson()}");
                }

                return(Ok(new OffchainSuccessTradeRespModel
                {
                    TransferId = response.TransferId,
                    TransactionHex = response.TransactionHex,
                    OperationResult = response.OperationResult,
                }));
            }
            catch (OffchainException ex)
            {
                return(await LogOffchainExceptionAndReturn(request, ControllerContext, ex));
            }
            catch (Exception ex)
            {
                return(await LogAndReturnNotFound(request, ControllerContext, ex.Message));
            }
        }