Exemple #1
0
 public void Ceiling__Produces_Correct_result(string a, string b)
 {
     Money18
     .Ceiling(Money18.Parse(a))
     .Should()
     .Be(b);
 }
Exemple #2
0
 public void Truncate__Produces_Correct_Result(string a, string b)
 {
     Money18
     .Truncate(Money18.Parse(a))
     .Should()
     .Be(b);
 }
 public void Money_Should_Be_Deserializable_From_Json()
 {
     JsonConvert
     .DeserializeObject <Money18>("\"10.00000\"")
     .Should()
     .Be(Money18.Create(10, 5));
 }
Exemple #4
0
 public void Round__Scale_Specified__Produces_Correct_Result(string a, string b)
 {
     Money18
     .Round(Money18.Parse(a), 2)
     .Should()
     .Be(b);
 }
        public async Task <TransferToExternalResultModel> TransferAsync(string customerId, string amount)
        {
            if (string.IsNullOrEmpty(customerId))
            {
                throw new ArgumentNullException(nameof(customerId));
            }

            if (string.IsNullOrEmpty(amount))
            {
                throw new ArgumentNullException(nameof(amount));
            }

            if (!Money18.TryParse(amount, out var amount18))
            {
                throw new FormatException("Amount is in wrong format");
            }

            var response = await _ccTransfersClient.Api.TransferToExternalAsync(
                new TransferToExternalRequest { CustomerId = customerId, Amount = amount18 });

            if (response.Error != TransferToExternalErrorCodes.None)
            {
                _log.Warning("Couldn't transfer to external wallet", context: new { customerId, amount, error = response.Error.ToString() });
            }

            return(_mapper.Map <TransferToExternalResultModel>(response));
        }
Exemple #6
0
 public override object ConvertFrom(
     ITypeDescriptorContext context,
     CultureInfo culture,
     object value)
 {
     return(Money18.Parse((string)value));
 }
        public async Task <TokensErrorCodes> SyncTotalTokensAsync()
        {
            try
            {
                var totalTokensFromPbf            = (await GetTotalTokensAsync()).TotalTokensAmount;
                var totalTokensOnTokenGateway     = (await GetTotalTokensOnTokenGatewayAsync()).TotalTokensAmount;
                var totalTokensOnCustomersWallets = totalTokensFromPbf - totalTokensOnTokenGateway;

                _log.Info($@"Manually synchronized Total Tokens from PBF service. Old value: {_totalTokensAmount},
                            new value: {totalTokensFromPbf}");

                _totalTokensAmount = totalTokensFromPbf;

                _log.Info($@"Manually synchronized Total Tokens on customer wallets from PBF service. Old value: {_totalTokensInCustomersWallets},
                            new value: {totalTokensOnCustomersWallets}");

                _totalTokensInCustomersWallets = totalTokensOnCustomersWallets;

                return(TokensErrorCodes.None);
            }
            catch
            {
                _log.Warning("Not able to get total tokens amount from pbf to Sync value");
                return(TokensErrorCodes.PrivateBlockchainFacadeIsNotAvailable);
            }
        }
        public void CompareTo__Integer_Value_Passed__Returns_Correct_Result()
        {
            var money = new Money18(42, 0);

            (money < 43).Should().BeTrue();
            (money > 41).Should().BeTrue();
            (money <= 43).Should().BeTrue();
            (money >= 41).Should().BeTrue();
            (money <= 42).Should().BeTrue();
            (money >= 42).Should().BeTrue();

            (43 > money).Should().BeTrue();
            (41 < money).Should().BeTrue();
            (43 >= money).Should().BeTrue();
            (41 <= money).Should().BeTrue();
            (42 <= money).Should().BeTrue();
            (42 >= money).Should().BeTrue();

            money
            .CompareTo(41)
            .Should()
            .BePositive();

            money
            .CompareTo(42)
            .Should()
            .Be(0);

            money
            .CompareTo(43)
            .Should()
            .BeNegative();
        }
Exemple #9
0
        private static Money18 CalculateTotalReward(CampaignDetails result)
        {
            var isApproximate = result.RewardType == RewardType.Percentage ||
                                result.RewardType == RewardType.ConversionRate;

            var earnRuleReward = isApproximate && result.ApproximateAward.HasValue ? result.ApproximateAward.Value : result.Reward;

            if (result.Conditions.Count == 1)
            {
                return(earnRuleReward);
            }

            Money18 conditionReward = 0m;

            foreach (var condition in result.Conditions)
            {
                var isApproximateCondition = condition.RewardType == RewardType.Percentage ||
                                             condition.RewardType == RewardType.ConversionRate;

                var conditionAmount = isApproximateCondition && condition.ApproximateAward.HasValue ?
                                      condition.ApproximateAward.Value : condition.ImmediateReward;

                conditionReward += conditionAmount;
            }

            var totalReward = conditionReward;

            return(totalReward);
        }
        private async Task SendNotificationAsync(string customerId, Money18 amount, Guid campaignId, Guid conditionId,
                                                 string requestId)
        {
            var campaign = await _campaignClient.History.GetEarnRuleByIdAsync(campaignId);

            if (campaign.ErrorCode != CampaignServiceErrorCodes.None)
            {
                _log.Error(message: "An error occurred while getting campaign",
                           context:
                           $"customerId: {customerId}; requestId: {requestId}; campaignId: {campaignId}; error: {campaign.ErrorCode}");
                return;
            }

            if (conditionId == Guid.Empty)
            {
                await _pushNotificationsPublisher.PublishCampaignCompletedAsync(customerId, amount, campaign.Name);
            }
            else
            {
                var condition = campaign.Conditions.FirstOrDefault(o => o.Id == conditionId.ToString());

                if (condition == null)
                {
                    _log.Error(message: "Campaign does not contains condition",
                               context:
                               $"customerId: {customerId}; requestId: {requestId}; campaignId: {campaignId}; conditionId: {conditionId}");
                    return;
                }

                await _pushNotificationsPublisher.PublishCampaignConditionCompletedAsync(customerId, amount,
                                                                                         campaign.Name, condition.TypeDisplayName);
            }
        }
        public async Task ProcessP2PTransferFailed(
            string contextId,
            string transactionHash,
            string senderCustomerId,
            string receiverCustomerId,
            Money18 amount,
            DateTime timestamp)
        {
            var transferContext = await _transfersRepository.GetAsync(contextId);

            if (transferContext == null)
            {
                _log.Error(message: "Context not found for p2p failed transfer",
                           context: new { requestId = contextId, transactionHash, senderCustomerId, receiverCustomerId });
                return;
            }

            var senderCurrentBalance = await GetCustomerCurrentBalance(senderCustomerId);

            var receiverEmail = await GetCustomerEmail(receiverCustomerId);

            var emailNotificationTask = _emailsPublisher.SendP2PFailedForSenderAsync(
                senderCustomerId,
                contextId,
                amount,
                timestamp,
                senderCurrentBalance,
                receiverEmail);

            var pushNotificationTask = _pushNotificationsPublisher.PublishP2PFailedForSenderAsync(senderCustomerId);

            await Task.WhenAll(emailNotificationTask, pushNotificationTask);

            await _transfersRepository.DeleteAsync(contextId);
        }
        private async Task <Money18> CalculateConditionRewardByPercentageAsync(Money18 percentage,
                                                                               ConditionCompletion conditionCompletion, string paymentId = null)
        {
            Money18 rewardsAmount = 0;

            foreach (var completionData in conditionCompletion.Data)
            {
                if (paymentId != null && completionData.ContainsKey(paymentId))
                {
                    var rewardDictionary = completionData[paymentId];

                    var paymentDictionary = JsonConvert.DeserializeObject <Dictionary <string, string> >(rewardDictionary);

                    rewardsAmount += Money18.Parse(paymentDictionary[AmountName]);
                }
                else if (paymentId == null && completionData != null && completionData.ContainsKey(AmountName))
                {
                    rewardsAmount += Money18.Parse(completionData[AmountName]);
                }
            }

            var amountInCurrency = rewardsAmount * (percentage / 100m);

            return(await GetEligibilityEngineAmountByCondition(conditionCompletion, amountInCurrency));
        }
        public Money18 CalculateRatioReward(IReadOnlyList <RatioAttribute> conditionRatios, Dictionary <string, string> conditionCompletionRewardDictionary, Money18 conditionReward)
        {
            Money18 reward         = 0m;
            var     ratiosForBonus = new List <RatioAttribute>();
            var     savedData      = JsonConvert.DeserializeObject <Dictionary <string, string> >(conditionCompletionRewardDictionary.Values.FirstOrDefault());

            if (savedData != null)
            {
                var purchaseCompletion = Convert.ToDecimal(savedData["PurchaseCompletionPercentage"]);
                var givenBonusFor      = Convert.ToDecimal(savedData["GivenRatioBonusPercent"]);

                foreach (var ratio in conditionRatios.OrderBy(r => r.Order))
                {
                    if (purchaseCompletion >= ratio.Threshold)
                    {
                        //in order not to give two times reward for 10%
                        if (givenBonusFor < ratio.Threshold)
                        {
                            ratiosForBonus.Add(ratio);
                        }
                    }
                }
            }

            foreach (var ratio in ratiosForBonus)
            {
                reward += ((Money18)ratio.RewardRatio / 100M) * conditionReward;
            }

            return(reward);
        }
Exemple #14
0
        public async Task <SpendRulesListResponseModel> GetSpendRulesAsync([FromQuery] PaginationRequestModel pagination)
        {
            var spendRules = await _campaignClient.Mobile.GetSpendRulesAsync(Localization.En, _mapper.Map <BasePaginationRequestModel>(pagination));

            var result = _mapper.Map <SpendRulesListResponseModel>(spendRules);

            foreach (var spendRule in result.SpendRules)
            {
                if (spendRule.BusinessVertical != BusinessVertical.Retail)
                {
                    continue;
                }

                var report = await _vouchersClient.Reports.GetSpendRuleVouchersAsync(spendRule.Id);

                spendRule.StockCount = report.InStock;
                spendRule.SoldCount  = report.Total - report.InStock;
                var rate = await _eligibilityEngineClient.ConversionRate.GetAmountBySpendRuleAsync(
                    new ConvertAmountBySpendRuleRequest()
                {
                    Amount       = Money18.Create(Math.Abs(spendRule.Price ?? 0)),
                    CustomerId   = Guid.Parse(_requestContext.UserId),
                    SpendRuleId  = spendRule.Id,
                    FromCurrency = _settingsService.GetBaseCurrencyCode(),
                    ToCurrency   = _settingsService.GetTokenName(),
                }
                    );

                spendRule.PriceInToken = rate.Amount.ToDisplayString();
            }

            return(result);
        }
Exemple #15
0
        public async Task HandleAsync(SmartVoucherSoldEvent message)
        {
            var partner = await _partnerManagementClient.Partners.GetByIdAsync(message.PartnerId);

            var customer =
                (await _customerProfileClient.CustomerProfiles.GetByCustomerIdAsync(message.CustomerId.ToString(), true, true))?.Profile;
            var campaign = await _smartVouchersClient.CampaignsApi.GetByIdAsync(message.CampaignId);

            var receiverEmail = partner.Locations.Count == 1 ? partner.Locations.First()?.ContactPerson?.Email : null;

            await _reportHelper.AddAsync(new TransactionReport
            {
                Amount          = Money18.Create(message.Amount),
                Id              = message.PaymentRequestId,
                PartnerId       = message.PartnerId.ToString(),
                Timestamp       = message.Timestamp,
                Vertical        = partner.BusinessVertical?.ToString(),
                Info            = message.VoucherShortCode,
                Currency        = message.Currency,
                TransactionType = TxType,
                SenderEmail     = customer?.Email,
                SenderName      = $"{customer?.FirstName} {customer?.LastName}",
                CampaignName    = campaign?.Name,
                Status          = VoucherStatus,
                CampaignId      = message.CampaignId,
                PartnerName     = partner?.Name,
                ReceiverName    = partner?.Name,
                ReceiverEmail   = receiverEmail,
            });
        }
Exemple #16
0
 public void Parse__Value_Correctly_Parsed(string a)
 {
     Money18
     .Parse(a)
     .Should()
     .Be(a);
 }
        public async Task HandleAsync(string privateAddress, Money18 amount, string eventId)
        {
            var isDuplicate = await _deduplicationLogRepository.IsDuplicateAsync(eventId);

            if (isDuplicate)
            {
                _log.Warning(message: "Duplicated TransferToExternalCompletedEvent found, processing won't continue further", context: eventId);
                return;
            }

            if (string.IsNullOrEmpty(privateAddress))
            {
                _log.Error(message: "Empty private address in TransferToExternalCompleted");
                return;
            }

            var customerIdResponse = await _pbfClient.CustomersApi.GetCustomerIdByWalletAddress(privateAddress);

            if (customerIdResponse.Error != CustomerWalletAddressError.None)
            {
                _log.Error(message: "Cannot find CustomerId from wallet address to handle TransferToExternalCompletedEvent",
                           context: new { privateAddress, customerIdResponse.Error });
                return;
            }

            await _pushNotificationsPublisher.PublishTransferToExternalSucceededAsync(customerIdResponse.CustomerId, amount);
        }
Exemple #18
0
        public async Task <OperationFeesModel> GetOperationFeesAsync()
        {
            var operationFees = new OperationFeesModel();

            var operationFeesConfig = await _crossChainWalletLinkerClient.ConfigurationApi.GetAllAsync();

            foreach (var model in operationFeesConfig)
            {
                switch (model.Type)
                {
                case ConfigurationItemType.FirstTimeLinkingFee:
                    operationFees.FirstTimeLinkingFee = Money18.Parse(model.Value);
                    break;

                case ConfigurationItemType.SubsequentLinkingFee:
                    operationFees.SubsequentLinkingFee = Money18.Parse(model.Value);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            var crossChainTransferFee = await _crossChainTransfersClient.FeesApi.GetTransferToPublicFeeAsync();

            operationFees.CrossChainTransferFee = crossChainTransferFee.Fee;

            return(operationFees);
        }
Exemple #19
0
        public async Task <Money18> GetNextWalletLinkingFeeAsync(Guid customerId)
        {
            if (customerId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(customerId));
            }

            var counter = await _counterRepository.GetAsync(customerId.ToString());

            var fee = await _configurationItemsRepository.GetAsync((counter?.ApprovalsCounter ?? 0) < 1
                                                                   ?ConfigurationItemType.FirstTimeLinkingFee
                                                                   : ConfigurationItemType.SubsequentLinkingFee);

            if (fee == null)
            {
                _log.Warning("Wallet linking fee has not been set, please use API to update it");

                return(0);
            }

            if (!Money18.TryParse(fee.Value, out var result))
            {
                _log.Error(message: "Couldn't parse Money18 from configuration value", context: new { fee = fee.Value });

                return(0);
            }

            return(result);
        }
        private async Task <Money18> GetCustomerCurrentBalance(string customerId)
        {
            Money18 amount = 0;

            try
            {
                var currentBalanceResponse =
                    await _blockchainFacadeClient.CustomersApi.GetBalanceAsync(Guid.Parse(customerId));

                if (currentBalanceResponse.Error == CustomerBalanceError.None)
                {
                    amount = currentBalanceResponse.Total;
                }

                else
                {
                    _log.Error(
                        message:
                        "Cannot process P2P failed transfer notifications cause a customer does not have a wallet",
                        context: customerId);
                }
            }
            catch (ClientApiException e)
            {
                _log.Error(e, "Cannot get customer balance when processing p2p failed event", customerId);
            }

            return(amount);
        }
 public void IncreaseBurnedAmount(Money18 amount)
 {
     lock (_locker)
     {
         _todaysBurnedAmount += amount;
     }
 }
Exemple #22
0
 public void Abs__Produces_Correct_Result(string a, string b)
 {
     Money18
     .Abs(Money18.Parse(a))
     .Should()
     .Be(b);
 }
Exemple #23
0
        protected override async Task ProcessMessageAsync(TransferToInternalDetectedEvent message)
        {
            await _handler.HandleAsync(message.OperationId, message.PrivateAddress, message.PublicAddress,
                                       Money18.Parse(message.Amount.ToString()), message.PublicTransferId);

            _log.Info("Processed TransferToInternalDetectedEvent", message);
        }
        public async Task HandleAsync(SmartVoucherUsedEvent message)
        {
            var partner = await _partnerManagementClient.Partners.GetByIdAsync(message.PartnerId);

            var customer =
                (await _customerProfileClient.CustomerProfiles.GetByCustomerIdAsync(message.CustomerId.ToString(), true, true))?.Profile;
            var campaign = await _smartVouchersClient.CampaignsApi.GetByIdAsync(message.CampaignId);

            await _reportHelper.AddAsync(new TransactionReport()
            {
                Amount          = Money18.Create(message.Amount),
                Id              = Guid.NewGuid().ToString(),
                PartnerId       = message.PartnerId.ToString(),
                Timestamp       = message.Timestamp,
                Currency        = message.Currency,
                TransactionType = TxType,
                CampaignName    = campaign?.Name,
                Status          = VoucherStatus,
                CampaignId      = message.CampaignId,
                Vertical        = partner.BusinessVertical?.ToString(),
                SenderEmail     = customer?.Email,
                SenderName      = $"{customer?.FirstName} {customer?.LastName}",
                PartnerName     = partner?.Name,
                Info            = message.VoucherShortCode,
            });
        }
Exemple #25
0
        public string FormatAmountToDisplayString(Money18 money18)
        {
            var formatInfo =
                new CultureInfo(_tokenFormatCultureInfo).NumberFormat;

            return(money18.ToString(_tokenIntegerPartFormat, _tokenNumberDecimalPlaces, formatInfo));
        }
        public void CompareTo__Decimal_Value_Passed__Returns_Correct_Result()
        {
            var money = new Money18(42, 0);

            (money < 43m).Should().BeTrue();
            (money > 41m).Should().BeTrue();
            (money <= 43m).Should().BeTrue();
            (money >= 41m).Should().BeTrue();
            (money <= 42m).Should().BeTrue();
            (money >= 42m).Should().BeTrue();

            (43m > money).Should().BeTrue();
            (41m < money).Should().BeTrue();
            (43m >= money).Should().BeTrue();
            (41m <= money).Should().BeTrue();
            (42m <= money).Should().BeTrue();
            (42m >= money).Should().BeTrue();

            money
            .CompareTo(41m)
            .Should()
            .BePositive();

            money
            .CompareTo(42m)
            .Should()
            .Be(0);

            money
            .CompareTo(43m)
            .Should()
            .BeNegative();
        }
        public async Task ProcessP2PTransferDetectedEventAsync(
            string contextId,
            string transactionHash,
            string senderCustomerId,
            string receiverCustomerId,
            Money18 amount,
            DateTime timestamp)
        {
            var transferContext = await _transfersRepository.GetAsync(contextId);

            if (transferContext == null)
            {
                _log.Error(message: ContextNotFoundMsg,
                           context: new { requestId = contextId, transactionHash, senderCustomerId, receiverCustomerId });
                throw new InvalidOperationException(ContextNotFoundMsg);
            }

            await _p2PTransferEventPublisher.PublishAsync(new P2PTransferEvent
            {
                Amount              = amount,
                Timestamp           = timestamp,
                SenderCustomerId    = senderCustomerId,
                ReceiverCustomerId  = receiverCustomerId,
                AssetSymbol         = transferContext.AssetSymbol,
                TransactionId       = transferContext.OperationId,
                ExternalOperationId = transferContext.ExternalOperationId
            });

            var senderCurrentBalance = await GetCustomerCurrentBalance(senderCustomerId);

            var receiverCurrentBalance = await GetCustomerCurrentBalance(receiverCustomerId);

            var senderCustomerEmail = await GetCustomerEmail(senderCustomerId);

            var receiverCustomerEmail = await GetCustomerEmail(receiverCustomerId);

            var senderEmailNotificationTask = _emailsPublisher.SendP2PSucceededForSenderAsync(senderCustomerId,
                                                                                              contextId, amount, timestamp, senderCurrentBalance,
                                                                                              receiverCustomerEmail);

            var receiverEmailNotificationTask = _emailsPublisher.SendP2PSucceededForReceiverAsync(receiverCustomerId,
                                                                                                  contextId, amount, timestamp, receiverCurrentBalance,
                                                                                                  senderCustomerEmail);

            var senderPushNotificationTask =
                _pushNotificationsPublisher.PublishP2PSucceededForSenderAsync(senderCustomerId);

            var receiverPushNotificationTask =
                _pushNotificationsPublisher.PublishP2PSucceededForReceiverAsync(receiverCustomerId, amount,
                                                                                senderCustomerEmail);

            await Task.WhenAll(
                senderEmailNotificationTask,
                receiverEmailNotificationTask,
                senderPushNotificationTask,
                receiverPushNotificationTask);

            await _transfersRepository.DeleteAsync(contextId);
        }
        public async Task <CurrencyConverterResponse> ConvertTokensToBaseCurrencyAsync(Money18 amount)
        {
            var result = await _currencyConverterClient.Converter.ConvertTokensToBaseCurrencyAsync(amount);

            return(new CurrencyConverterResponse {
                Amount = Money18.Create(result.Amount).ToDisplayString()
            });
        }
Exemple #29
0
 public BaseConversionRateRequestValidator()
 {
     RuleFor(r => r.Amount)
     .NotNull()
     .NotEmpty()
     .Must(r => r != null && Money18.TryParse(r, out var money18) && money18 > 0)
     .WithMessage("Amount should be valid number greater than 0.");
 }
        private async Task <Money18?> GetCachedValue(string walletAddress)
        {
            var value = await _distributedCache.GetStringAsync(GetCacheKey(walletAddress));

            return(string.IsNullOrEmpty(value)
                ? new Money18?()
                : Money18.Parse(value));
        }