private async Task <GetDepositAddressResponse> GetBitgoDepositAddressAsync(GetDepositAddressRequest request)
        {
            try
            {
                var(bitgoCoin, bitgoWalletId) =
                    _assetMapper.AssetToBitgoCoinAndWallet(request.BrokerId, request.AssetSymbol);

                if (string.IsNullOrEmpty(bitgoWalletId) || string.IsNullOrEmpty(bitgoCoin))
                {
                    _logger.LogError(
                        "Cannot process GetDepositAddress. Asset do not mapped to bitgo. Request: {jsonText}",
                        JsonConvert.SerializeObject(request));
                    return(new GetDepositAddressResponse
                    {
                        Error = GetDepositAddressResponse.ErrorCode.AssetDoNotSupported
                    });
                }

                Error error = null;

                var label = _walletMapper.WalletToBitgoLabel(new JetWalletIdentity
                {
                    BrokerId = request.BrokerId,
                    ClientId = request.ClientId,
                    WalletId = request.WalletId
                });

                await using var ctx = DatabaseContext.Create(_dbContextOptionsBuilder);
                var addressEntity = await ctx.Addresses.Where(t =>
                                                              t.BrokerId == request.BrokerId && t.ClientId == request.ClientId &&
                                                              t.WalletId == request.WalletId && t.Blockchain == request.Blockchain &&
                                                              t.AssetSymbol == request.AssetSymbol).FirstOrDefaultAsync();

                var address = addressEntity?.Address;

                if (string.IsNullOrEmpty(address))
                {
                    (address, error) =
                        await _depositAddressGeneratorService.GetAddressAsync(bitgoCoin, bitgoWalletId, label);
                }

                if (string.IsNullOrEmpty(address))
                {
                    var preGeneratedAddresses = (await _generatedAddressDataWriter.GetAsync(
                                                     GeneratedDepositAddressEntity.GeneratePartitionKey(request.BrokerId, bitgoCoin,
                                                                                                        bitgoWalletId, request.Blockchain)))
                                                .ToList();

                    if (preGeneratedAddresses.Count > 0)
                    {
                        var preGeneratedAddress = preGeneratedAddresses.First();
                        (address, error) = await _depositAddressGeneratorService.UpdateAddressLabelAsync(bitgoCoin,
                                                                                                         bitgoWalletId,
                                                                                                         preGeneratedAddress.Address.BitGoAddressId, label);

                        if (error == null)
                        {
                            await _generatedAddressDataWriter.DeleteAsync(preGeneratedAddress.PartitionKey,
                                                                          preGeneratedAddress.RowKey);
                        }
                    }
                    else
                    {
                        (address, error) =
                            await _depositAddressGeneratorService.GenerateAddressAsync(bitgoCoin, bitgoWalletId, label);
                    }
                }

                if (string.IsNullOrEmpty(address) || error != null)
                {
                    _logger.LogError(
                        "Cannot process GetDepositAddress. Unable to generate address. Request: {jsonText}. Error: {error}",
                        JsonConvert.SerializeObject(request), error);
                    return(new GetDepositAddressResponse
                    {
                        Error = GetDepositAddressResponse.ErrorCode.AddressNotGenerated
                    });
                }

                if (addressEntity == null)
                {
                    await ctx.InsertAsync(new DepositAddressSqlEntity
                    {
                        BrokerId    = request.BrokerId,
                        ClientId    = request.ClientId,
                        WalletId    = request.WalletId,
                        Integration = "BitGo",
                        AssetSymbol = request.AssetSymbol,
                        Blockchain  = request.Blockchain,
                        Address     = address,
                        CreatedDate = DateTime.Now
                    });
                }

                await _addressDataWriter.InsertOrReplaceAsync(DepositAddressEntity.Create(request.WalletId,
                                                                                          request.AssetSymbol, request.Blockchain, address));

                await _addressDataWriter.CleanAndKeepMaxPartitions(Program.Settings.MaxClientInCache);

                _logger.LogInformation("Handle GetDepositAddress, request: {jsonText}, address: {address}",
                                       JsonConvert.SerializeObject(request), address);

                return(new GetDepositAddressResponse
                {
                    Address = address,
                    Error = GetDepositAddressResponse.ErrorCode.Ok
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Exception on GetDepositAddress with request: {jsonText}",
                                 JsonConvert.SerializeObject(request));
                throw;
            }
        }
        public async Task <GetBitGoWalletLimitsResponse> GetSpendingLimitsAsync(GetBitGoWalletLimitsRequest request)
        {
            try
            {
                var(coin, wallet) = _assetMapper.AssetToBitgoCoinAndWallet(request.BrokerId, request.AssetId);

                var client = _bitGoClientService.GetByUser(request.BrokerId, BitGoUserNoSqlEntity.TechSignerId, coin);
                if (client == null)
                {
                    return(new GetBitGoWalletLimitsResponse
                    {
                        Success = false,
                        Error = $"Tech account is not configured, id = {BitGoUserNoSqlEntity.TechSignerId}, coin = {coin}"
                    });
                }

                var result = await client.GetSpendingLimitsForWalletAsync(coin, wallet);

                if (!result.Success)
                {
                    _logger.LogInformation(
                        $"Unable to get spending limits: {JsonConvert.SerializeObject(result.Error)}");
                    return(new GetBitGoWalletLimitsResponse
                    {
                        Success = false,
                        Error = result.Error.Message
                    });
                }

                var limit = new SpendingLimit
                {
                    AssetId   = request.AssetId,
                    BitgoCoin = coin
                };

                foreach (var spendingLimit in result.Data.Limits)
                {
                    if (spendingLimit.Coin == coin)
                    {
                        switch (spendingLimit.TimeWindow)
                        {
                        case "0":
                            limit.TransactionLimit =
                                _assetMapper.ConvertAmountFromBitgo(coin, decimal.Parse(spendingLimit.LimitAmountString));
                            break;

                        case "3600":
                            limit.HourlyLimit =
                                _assetMapper.ConvertAmountFromBitgo(coin, decimal.Parse(spendingLimit.LimitAmountString));
                            limit.HourlySpent =
                                _assetMapper.ConvertAmountFromBitgo(coin, decimal.Parse(spendingLimit.AmountSpentString));
                            break;

                        case "86400":
                            limit.DailyLimit =
                                _assetMapper.ConvertAmountFromBitgo(coin, decimal.Parse(spendingLimit.LimitAmountString));
                            limit.DailySpent =
                                _assetMapper.ConvertAmountFromBitgo(coin, decimal.Parse(spendingLimit.AmountSpentString));
                            break;
                        }
                    }
                }

                return(new GetBitGoWalletLimitsResponse
                {
                    Success = true,
                    Limit = limit
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "GetSpendingLimitsAsync request error: {message}", ex.Message);
                throw;
            }
        }