public async Task <Voucher> BuyAsync(Guid customerId, Guid spendRuleId) { var customerProfileResponse = await _customerProfileClient.CustomerProfiles.GetByCustomerIdAsync(customerId.ToString()); if (customerProfileResponse?.Profile == null) { throw new CustomerNotFoundException(); } var customerWalletStatusResponse = await _walletManagementClient.Api.GetCustomerWalletBlockStateAsync(customerId.ToString()); if (customerWalletStatusResponse.Status == CustomerWalletActivityStatus.Blocked) { throw new CustomerWalletBlockedException(); } var spendRuleResult = await _campaignClient.BurnRules.GetByIdAsync(spendRuleId); if (spendRuleResult.ErrorCode == CampaignServiceErrorCodes.EntityNotFound) { throw new SpendRuleNotFoundException(); } if (spendRuleResult.Vertical != Vertical.Retail) { throw new InvalidSpendRuleVerticalException(); } if (!spendRuleResult.Price.HasValue) { throw new InvalidSpendRulePriceException(); } var amount = await ConvertVoucherPriceToTokensAsync(customerId, spendRuleId, spendRuleResult.Price.Value); var customerBalanceResponse = await _privateBlockchainFacadeClient.CustomersApi.GetBalanceAsync(customerId); if (customerBalanceResponse.Total - customerBalanceResponse.Staked < amount) { throw new NoEnoughTokensException(); } var voucher = await _vouchersService.ReserveAsync(spendRuleId, customerId, spendRuleResult.Price.Value, amount); try { await _transfersService.CreateAsync(customerId, spendRuleId, voucher.Id, amount); } catch { await _vouchersService.ReleaseAsync(voucher.Id); throw; } return(voucher); }