public async Task <OffchainResult> CreateHubCommitment(string clientId, string transferId, string signedChannel)
        {
            var credentials = await _walletCredentialsRepository.GetAsync(clientId);

            var offchainTransfer = await _offchainTransferRepository.GetTransfer(transferId);

            if (offchainTransfer.Completed)
            {
                await _logger.WriteErrorAsync("CreateHubCommitment", (new { ClientId = clientId, TransferId = transferId }).ToJson() + " Offchain transfer already completed!", new OffchainException(ErrorCode.Exception, offchainTransfer.AssetId));

                throw new OffchainException(ErrorCode.Exception, offchainTransfer.AssetId);
            }


            if (offchainTransfer.ClientId != clientId)
            {
                await _logger.WriteErrorAsync("CreateHubCommitment", (new { ClientId = clientId, TransferId = transferId }).ToJson() + $" Offchain transfer set for a different client: offchainTransfer.ClientId=={offchainTransfer.ClientId}!", new OffchainException(ErrorCode.Exception, offchainTransfer.AssetId));

                throw new OffchainException(ErrorCode.Exception, offchainTransfer.AssetId);
            }

            var amount = 0.0M;

            switch (offchainTransfer.Type)
            {
            case OffchainTransferType.DirectTransferFromClient:
                amount = -offchainTransfer.Amount;
                break;

            default: throw new OffchainException(ErrorCode.OperationNotSupported, $"Unsuported offchainTransfer.Type: {offchainTransfer.Type} while initializing CreateHubCommitment.", "", "", false);
            }

            var result = await _bitcoinApiClient.CreateHubCommitment(new CreateHubComitmentData
            {
                Amount                = amount,
                ClientPubKey          = credentials.PublicKey,
                AssetId               = offchainTransfer.AssetId,
                SignedByClientChannel = signedChannel
            });

            if (result.HasError)
            {
                return(await InternalErrorProcessing("ProcessClientTransfer", result.Error, credentials, offchainTransfer, required : false));
            }

            return(new OffchainResult
            {
                TransferId = offchainTransfer.Id,
                TransactionHex = result.Transaction,
                OperationResult = OffchainOperationResult.Transfer
            });
        }
        public async Task Process(OffchainFinalizetionMessage message)
        {
            var transfer = await _offchainTransferRepository.GetTransfer(message.TransferId);

            if (transfer.Type == OffchainTransferType.HubCashout || transfer.Type == OffchainTransferType.CashinFromClient)
            {
                return;
            }

            var transactionId =
                transfer.Type == OffchainTransferType.FromClient || transfer.Type == OffchainTransferType.FromHub
                    ? transfer.OrderId
                    : transfer.Id;

            var transaction = await _bitCoinTransactionsRepository.SaveResponseAndHashAsync(transactionId, null, message.TransactionHash);

            if (transaction == null)
            {
                await _log.WriteWarningAsync(nameof(OffchainTransactionFinalizeFunction), nameof(Process), $"Transaction: {transactionId}, client: {message.ClientId}, hash: {message.TransactionHash}, transfer: {message.TransferId}", "unkown transaction");

                return;
            }

            switch (transaction.CommandType)
            {
            case BitCoinCommands.Issue:
                await FinalizeIssue(transaction);

                break;

            case BitCoinCommands.CashOut:
                await FinalizeCashOut(transaction, transfer);

                break;

            case BitCoinCommands.Transfer:
                await FinalizeTransfer(transaction, transfer);

                break;

            case BitCoinCommands.SwapOffchain:
                await FinalizeSwap(transaction, transfer);

                break;

            default:
                await _log.WriteWarningAsync(nameof(OffchainTransactionFinalizeFunction), nameof(Process), $"Transaction: {transactionId}, client: {message.ClientId}, hash: {message.TransactionHash}, transfer: {message.TransferId}", "unkown command type");

                break;
            }
        }
예제 #3
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);
        }
예제 #4
0
        private async void AttachSenderTransferToRefLink(IReferralLink refLink, string transferId)
        {
            var transfer = await _offchainTransferRepository.GetTransfer(transferId);

            refLink.Amount = (double)transfer.Amount;
            refLink.Asset  = (await _assets.GetItemAsync(transfer.AssetId)).Id;
            refLink.SenderOffchainTransferId = transferId;
            refLink.State = ReferralLinkState.SentToLykkeSharedWallet.ToString();

            await _referralLinksService.UpdateAsync(refLink);

            await LogInfo(new { RefLink = refLink, TransferId = transferId }, ControllerContext, $"Transfer complete for ref link id {refLink.Id} with amount {transfer.Amount} and asset Id {refLink.Asset}. Offchain transfer Id {transferId} attached with ref link. ");
        }