Пример #1
0
        private async ValueTask HandleSignal(SignalCircleTransfer signal)
        {
            using var activity = MyTelemetry.StartActivity("Handle event SignalCircleTransfer");
            signal.AddToActivityAsJsonTag("circle-signal");

            _logger.LogInformation("SignalCircleTransfer is received: {jsonText}", JsonConvert.SerializeObject(signal));

            if (signal.PaymentInfo == null)
            {
                _logger.LogError("Cannot handle Circle signal, transfer do not found {jsonText}",
                                 JsonConvert.SerializeObject(signal));
                Activity.Current?.SetStatus(Status.Error);
                return;
            }

            if (signal.PaymentInfo.Source.Type != "wallet")
            {
                _logger.LogInformation("Skip non-withdrawal transfer {type}", signal.PaymentInfo.Source.Type);
                return;
            }

            if (signal.PaymentInfo.Status == PaymentStatus.Pending)
            {
                await UpdateWithTransactionDetails(signal);

                return;
            }

            if (signal.PaymentInfo.Status != PaymentStatus.Complete)
            {
                _logger.LogInformation("SignalCircleTransfer is not completed, skipping");
                return;
            }

            await HandleTransactionFee(signal);

            _logger.LogInformation("SignalCircleTransfer is handled");
        }
        public async Task HandledDepositAsync(SignalCircleTransfer transfer)
        {
            transfer.AddToActivityAsJsonTag("circle-transfer");

            _logger.LogInformation("Request to handle transfer from Circle: {transferJson}",
                                   JsonConvert.SerializeObject(transfer));

            if (transfer.PaymentInfo.Source.Type != "blockchain" && transfer.PaymentInfo.Source.Type != "card")
            {
                _logger.LogInformation("Skip withdrawal transfer {type}", transfer.PaymentInfo.Source.Type);
                return;
            }

            transfer.BrokerId.AddToActivityAsTag("brokerId");
            transfer.WalletId.AddToActivityAsTag("walletId");
            transfer.ClientId.AddToActivityAsTag("clientId");

            var    circleAsset = _circleAssetMapper.CircleAssetToAsset(transfer.BrokerId, transfer.PaymentInfo.Amount.Currency);
            string asset       = null;

            if (transfer.PaymentInfo.Source.Type == "card")
            {
                asset = circleAsset?.AssetSymbol;
            }
            else if (transfer.PaymentInfo.Source.Type == "blockchain")
            {
                asset = circleAsset?.AssetTokenSymbol;
            }

            if (string.IsNullOrEmpty(asset))
            {
                _logger.LogError("Unknown circle asset {asset}", transfer.PaymentInfo.Amount.Currency);
                return;
            }

            var accuracy = _assetsDictionary.GetAssetById(new AssetIdentity
            {
                Symbol   = asset,
                BrokerId = transfer.BrokerId
            }).Accuracy;

            var amount    = (decimal)double.Parse(transfer.PaymentInfo.Amount.Amount);
            var feeAmount = (decimal)double.Parse(string.IsNullOrEmpty(transfer.PaymentInfo?.Fees?.Amount)
                ? "0.0"
                : transfer.PaymentInfo.Fees.Amount);

            var roundedAmount = Math.Round(amount - feeAmount, accuracy, MidpointRounding.ToNegativeInfinity);

            var isBlockchain     = transfer.PaymentInfo.Source.Type == "blockchain";
            var circleBlockchain =
                _circleBlockchainMapper.BlockchainToCircleBlockchain(transfer.BrokerId,
                                                                     transfer.PaymentInfo.Source.Chain);

            try
            {
                await using var ctx = DatabaseContext.Create(_dbContextOptionsBuilder);
                var existingEntity =
                    await ctx.Deposits.Where(e => e.TransactionId == transfer.PaymentInfo.Id).FirstOrDefaultAsync();

                if (existingEntity == null)
                {
                    _logger.LogInformation("Got unknown deposit from circle, adding entry");
                    existingEntity = new DepositEntity
                    {
                        BrokerId      = transfer.BrokerId,
                        WalletId      = transfer.WalletId,
                        ClientId      = transfer.ClientId,
                        TransactionId = transfer.PaymentInfo.Id,
                        Amount        = (decimal)roundedAmount,
                        AssetSymbol   = asset,
                        Comment       = isBlockchain
                            ? $"Circle blockchain {transfer.PaymentInfo.Source.Chain} deposit [{asset}]"
                            :
                                        $"Circle card deposit [{asset}:{transfer.WalletId}, card: {transfer.PaymentInfo.Source.Id}]",
                        Integration    = isBlockchain ? "CircleBlockchain" : "CircleCard",
                        Txid           = isBlockchain ? transfer.PaymentInfo.TransactionHash : transfer.PaymentInfo.Id,
                        Status         = ConvertExternalStatus(transfer.PaymentInfo.Status),
                        EventDate      = DateTime.UtcNow,
                        UpdateDate     = DateTime.UtcNow,
                        FeeAmount      = feeAmount,
                        FeeAssetSymbol = string.IsNullOrEmpty(transfer.PaymentInfo?.Fees?.Currency)
                            ? transfer.PaymentInfo.Amount.Currency
                            : transfer.PaymentInfo.Fees.Currency,
                        Network = circleBlockchain != null
                            ? circleBlockchain.Blockchain
                            : transfer.PaymentInfo.Source.Chain,
                        MatchingEngineId = "Deposit:" + Guid.NewGuid(),
                    };
                }
                else
                {
                    existingEntity.Amount         = roundedAmount;
                    existingEntity.UpdateDate     = DateTime.UtcNow;
                    existingEntity.FeeAmount      = feeAmount;
                    existingEntity.FeeAssetSymbol = string.IsNullOrEmpty(transfer.PaymentInfo?.Fees?.Currency)
                        ? transfer.PaymentInfo.Amount.Currency
                        : transfer.PaymentInfo.Fees.Currency;
                    existingEntity.Status = ConvertExternalStatus(transfer.PaymentInfo.Status);
                }

                await ctx.UpsertAsync(existingEntity);

                await _depositPublisher.PublishAsync(new Deposit(existingEntity));
            }
            catch (Exception)
            {
                _logger.LogError("Unable to update deposit entry");
                throw;
            }

            _logger.LogInformation("Deposit request from Circle {transferIdString} is handled",
                                   transfer.PaymentInfo.Id);
        }