Example #1
0
        public async Task <AssetIdentity> PutIdentity(AssetIdentity note)
        //     public async Task<IActionResult> Index([FromForm]IFormFile file)
        {
            var userId = (string)HttpContext.Items["User"];
            UserDetailsRequest userDetailsRequest = new UserDetailsRequest();

            userDetailsRequest.id = userId;

            var userDetails = await _kistService.UsersDetails(userDetailsRequest);

            note.modifiedBy = userDetails.Forename + " " + userDetails.Surname;
            note.modifiedOn = DateTime.Now;
            return(await _kistService.PutIdentity(note));
        }
        public async Task <GetDepositAddressResponse> GetDepositAddressAsync(GetDepositAddressRequest request)
        {
            var assetIdentity = new AssetIdentity
            {
                BrokerId = request.BrokerId,
                Symbol   = request.AssetSymbol
            };

            var paymentSettings = _assetPaymentSettingsClient.GetAssetById(assetIdentity);

            if (paymentSettings?.BitGoCrypto?.IsEnabledDeposit == true)
            {
                return(await GetBitgoDepositAddressAsync(request));
            }
            if (paymentSettings?.Circle?.IsEnabledBlockchainDeposit == true)
            {
                return(await GeCircleDepositAddressAsync(request));
            }

            return(new GetDepositAddressResponse
            {
                Error = GetDepositAddressResponse.ErrorCode.AddressNotGenerated
            });
        }
Example #3
0
        public async Task <CryptoWithdrawalResponse> CryptoWithdrawalAsync(CryptoWithdrawalRequest request)
        {
            _logger.LogDebug("Receive CryptoWithdrawalRequest: {jsonText}", JsonConvert.SerializeObject(request));
            request.WalletId.AddToActivityAsTag("walletId");
            request.ClientId.AddToActivityAsTag("clientId");
            request.BrokerId.AddToActivityAsTag("brokerId");
            request.ToAddress.AddToActivityAsTag("blockchain-address");

            try
            {
                var    feeAmount         = 0m;
                string feeAsset          = null;
                string comment           = null;
                string integration       = null;
                string destinationWallet = null;
                string destinationClient = null;

                var requestId     = request.RequestId ?? Guid.NewGuid().ToString("N");
                var transactionId = OperationIdGenerator.GenerateOperationId(requestId, request.WalletId);

                var addressInfoResponse = await _walletService.GetUserByAddressAsync(new Blockchain.Wallets.Grpc.Models.UserWallets.GetUserByAddressRequest
                {
                    Addresses = new Blockchain.Wallets.Grpc.Models.UserWallets.GetUserByAddressRequest.AddressAndTag[]
                    {
                        new Blockchain.Wallets.Grpc.Models.UserWallets.GetUserByAddressRequest.AddressAndTag
                        {
                            Address = request.ToAddress,
                            Tag     = string.IsNullOrEmpty(request.ToTag) ? null : request.ToTag,
                        }
                    },
                });

                var assetIdentity = new AssetIdentity
                {
                    BrokerId = request.BrokerId,
                    Symbol   = request.AssetSymbol
                };

                var paymentSettings = _assetPaymentSettingsClient.GetAssetById(assetIdentity);

                var isInternal = addressInfoResponse.Users != null && addressInfoResponse.Users.Any();
                if (isInternal)
                {
                    var existingAddress  = addressInfoResponse.Users.First();
                    var clientIdResponse = await _clientWalletService.SearchClientsAsync(new SearchWalletsRequest()
                    {
                        SearchText = existingAddress.WalletId,
                        Take       = 1
                    });

                    destinationClient = clientIdResponse.Clients.FirstOrDefault()?.ClientId;

                    destinationWallet = existingAddress.WalletId;
                    comment           = $"Internal withdrawal [{request.AssetSymbol}:{request.Amount}:{request.WalletId}]";
                    integration       = "Internal";

                    if (destinationClient == request.ClientId)
                    {
                        return(new CryptoWithdrawalResponse()
                        {
                            Error = new BitgoErrorType()
                            {
                                Code = BitgoErrorType.ErrorCode.AddressIsNotValid,
                                Message = "Cannot send fund to yourself"
                            }
                        });
                    }
                }
                else
                {
                    if (paymentSettings?.Fireblocks?.IsEnabledWithdrawal == true)
                    {
                        comment     = $"Fireblocks withdrawal [{request.AssetSymbol}:{request.Amount}:{request.WalletId}]";
                        integration = "Fireblocks";
                    }
                    else if (paymentSettings?.Circle?.IsEnabledBlockchainWithdrawal == true)
                    {
                        var isGuidValid = Guid.TryParse(request.RequestId, out _);
                        if (!isGuidValid)
                        {
                            return(new CryptoWithdrawalResponse()
                            {
                                Error = new BitgoErrorType()
                                {
                                    Message =
                                        $"RequestId should be Guid {request.RequestId}",
                                    Code = BitgoErrorType.ErrorCode.InvalidRequestId
                                }
                            });
                        }

                        var circleAsset = _circleAssetMapper.AssetToCircleTokenAsset(request.BrokerId, request.AssetSymbol);

                        if (circleAsset == null)
                        {
                            _logger.LogInformation(
                                $"[CryptoWithdrawalRequest] Cannot found circle coin association for asset {request.AssetSymbol}, broker {request.BrokerId}");

                            return(new CryptoWithdrawalResponse()
                            {
                                Error = new BitgoErrorType()
                                {
                                    Message =
                                        $"Cannot found circle coin association for asset {request.AssetSymbol}, broker {request.BrokerId}",
                                    Code = BitgoErrorType.ErrorCode.AssetIsNotFoundInCircle
                                }
                            });
                        }

                        var circleBlockchain =
                            _circleBlockchainMapper.BlockchainToCircleBlockchain(request.BrokerId, request.Blockchain);

                        if (circleBlockchain == null)
                        {
                            _logger.LogInformation(
                                $"[CryptoWithdrawalRequest] Cannot found circle blockchain association for blockchain {request.Blockchain}, broker {request.BrokerId}");

                            return(new CryptoWithdrawalResponse()
                            {
                                Error = new BitgoErrorType()
                                {
                                    Message =
                                        $"Cannot found circle blockchain association for blockchain {request.Blockchain}, broker {request.BrokerId}",
                                    Code = BitgoErrorType.ErrorCode.BlockchainIsNotFoundInCircle
                                }
                            });
                        }

                        comment       = $"Circle withdrawal [{request.AssetSymbol}:{request.Amount}:{request.WalletId}]";
                        integration   = "Circle";
                        transactionId = requestId;
                    }

                    var fees = _assetFeesClient.GetAssetFees(request.BrokerId, request.AssetSymbol,
                                                             OperationType.Withdrawal);

                    if (fees != null)
                    {
                        feeAsset = fees.AssetId;
                        if (feeAsset == request.AssetSymbol)
                        {
                            feeAmount = fees.FeeSizeType == FeeSizeType.Absolute
                                ? (decimal)fees.FeeSize
                                : (decimal)fees.FeeSize / 100 * request.Amount;
                        }
                        else
                        {
                            feeAmount = (decimal)fees.FeeSize;
                        }
                    }
                }


                await using var ctx = DatabaseContext.Create(_dbContextOptionsBuilder);
                var withdrawalEntity = new WithdrawalEntity()
                {
                    BrokerId            = request.BrokerId,
                    ClientId            = request.ClientId,
                    WalletId            = request.WalletId,
                    TransactionId       = transactionId,
                    Amount              = request.Amount,
                    AssetSymbol         = request.AssetSymbol,
                    Comment             = comment,
                    Integration         = integration,
                    Status              = WithdrawalStatus.New,
                    EventDate           = DateTime.UtcNow,
                    ToAddress           = request.ToAddress,
                    ToTag               = request.ToTag,
                    ClientIp            = request.ClientIp,
                    ClientLang          = request.ClientLang,
                    FeeAmount           = feeAmount,
                    FeeAssetSymbol      = feeAsset,
                    IsInternal          = isInternal,
                    DestinationWalletId = destinationWallet,
                    DestinationClientId = destinationClient,
                    Blockchain          = request.Blockchain,
                    Signature           = request.Signature,
                    SignatureIssuedAt   = request.SignatureIssuedAtUnixTime,
                };
                try
                {
                    await ctx.AddAsync(withdrawalEntity);

                    await ctx.SaveChangesAsync();
                }
                catch (Exception)
                {
                    var existingWithdrawal =
                        await ctx.Withdrawals.Where(t => t.TransactionId == transactionId).FirstAsync();

                    return(new CryptoWithdrawalResponse()
                    {
                        OperationId = existingWithdrawal.Id.ToString()
                    });
                }

                return(new CryptoWithdrawalResponse
                {
                    OperationId = withdrawalEntity.Id.ToString()
                });
            }
            catch (Exception ex)
            {
                ex.FailActivity();
                _logger.LogError(ex, "Cannot handle CryptoWithdrawalRequest {jsonText}",
                                 JsonConvert.SerializeObject(request));
                return(new CryptoWithdrawalResponse()
                {
                    Error = new BitgoErrorType()
                    {
                        Code = BitgoErrorType.ErrorCode.InternalError,
                        Message = ex.Message
                    }
                });
            }
        }
        private async Task DoTime()
        {
            var maxCount = Program.ReloadedSettings(e => e.PreGeneratedAddressesCount).Invoke();
            var wallets  = await _bitGoAssetMapSettingsService.GetAllAssetMapsAsync();

            foreach (var wallet in wallets)
            {
                var assetIdentity = new AssetIdentity
                {
                    BrokerId = wallet.BrokerId,
                    Symbol   = wallet.AssetSymbol
                };

                var paymentSettings = _assetPaymentSettingsClient.GetAssetById(assetIdentity);
                if (paymentSettings?.BitGoCrypto?.IsEnabledDeposit != true)
                {
                    continue;
                }

                var asset = _assetsDictionaryClient.GetAssetById(assetIdentity);

                if (asset == null || !asset.IsEnabled)
                {
                    continue;
                }

                var blockchain = asset.DepositBlockchains.FirstOrDefault();
                if (string.IsNullOrEmpty(blockchain))
                {
                    continue;
                }

                var entitiesCount = await _dataWriter.GetCountAsync(
                    GeneratedDepositAddressEntity.GeneratePartitionKey(wallet.BrokerId, wallet.BitgoCoin,
                                                                       wallet.BitgoWalletId, blockchain));

                if (entitiesCount < maxCount)
                {
                    for (var i = 1; i <= maxCount - entitiesCount; i++)
                    {
                        try
                        {
                            var id    = Guid.NewGuid().ToString();
                            var label = $"PreGenerated-{id}";
                            var(addressId, address, error) =
                                await _depositAddressGeneratorService.GenerateOrGetAddressIdAsync(wallet.BitgoCoin,
                                                                                                  wallet.BitgoWalletId, label);

                            if (string.IsNullOrEmpty(addressId) || error != null)
                            {
                                _logger.LogError(
                                    "Unable to pre-generate address for broker {broker}, asset {asset}, wallet id {walletId}: {error}",
                                    wallet.BrokerId, wallet.BitgoCoin, wallet.BitgoWalletId, error);
                                continue;
                            }

                            await _dataWriter.InsertAsync(GeneratedDepositAddressEntity.Create(
                                                              new GeneratedDepositAddress
                            {
                                BrokerId             = wallet.BrokerId,
                                Asset                = wallet.BitgoCoin,
                                WalletId             = wallet.BitgoWalletId,
                                PreGeneratedWalletId = id,
                                AddressLabel         = label,
                                Address              = address,
                                BitGoAddressId       = addressId,
                                Blockchain           = blockchain
                            }));
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(ex,
                                             "Unable to pre-generate address for broker {broker}, asset {asset}, wallet id {walletId}, blockchain {blockchain}",
                                             wallet.BrokerId, wallet.BitgoCoin, wallet.BitgoWalletId, blockchain);
                        }
                    }

                    _logger.LogInformation(
                        "Pre-generated {count} addresses for broker {broker}, asset {asset}, wallet id {walletId}, blockchain {blockchain}",
                        maxCount - entitiesCount, wallet.BrokerId, wallet.BitgoCoin, wallet.BitgoWalletId, blockchain);
                }
            }
        }