public async Task <ReferralStakesStatusUpdateErrorCode> TokensBurnAndReleaseAsync(string referralId, decimal?releaseBurnRatio = null) { if (string.IsNullOrEmpty(referralId)) { throw new ArgumentNullException(nameof(referralId)); } var newStatus = StakeStatus.TokensBurnAndReleaseStarted; var transactionError = await _transactionRunner.RunWithTransactionAsync(async txContext => { var referralStake = await _referralStakesRepository.GetByReferralIdAsync(referralId, txContext); if (referralStake == null) { return(ReferralStakesStatusUpdateErrorCode.DoesNotExist); } if (referralStake.Status != StakeStatus.TokensReservationSucceeded) { return(ReferralStakesStatusUpdateErrorCode.InvalidStatus); } var customerWalletAddress = await _pbfClient.CustomersApi.GetWalletAddress(Guid.Parse(referralStake.CustomerId)); if (customerWalletAddress.Error == CustomerWalletAddressError.CustomerWalletMissing) { return(ReferralStakesStatusUpdateErrorCode.CustomerWalletIsMissing); } var walletBlockStatus = await _walletManagementClient.Api.GetCustomerWalletBlockStateAsync(referralStake.CustomerId); if (walletBlockStatus.Status == CustomerWalletActivityStatus.Blocked) { return(ReferralStakesStatusUpdateErrorCode.CustomerWalletBlocked); } referralStake.Status = newStatus; referralStake.ReleaseBurnRatio = releaseBurnRatio; var burnRatio = releaseBurnRatio ?? referralStake.ExpirationBurnRatio; var(amountToBurn, amountToRelease) = CalculateAmountToBurnAndRelease(referralStake.Amount, burnRatio); var encodedData = _blockchainEncodingService.EncodeDecreaseRequestData(customerWalletAddress.WalletAddress, amountToBurn, amountToRelease); var operationId = await AddBlockchainOperation(encodedData); await _stakesBlockchainDataRepository.UpsertAsync(referralId, operationId, txContext); await _referralStakesRepository.UpdateReferralStakeAsync(referralStake, txContext); return(ReferralStakesStatusUpdateErrorCode.None); }); if (transactionError == ReferralStakesStatusUpdateErrorCode.None) { await PublishStatusUpdatedEvent(referralId, newStatus); } return(transactionError); }
public async Task <ReferralStakeRequestErrorCode> ReferralStakeAsync(ReferralStakeModel model) { #region Validation if (string.IsNullOrEmpty(model.CustomerId)) { throw new ArgumentNullException(nameof(model.CustomerId)); } if (string.IsNullOrEmpty(model.CampaignId)) { throw new ArgumentNullException(nameof(model.CampaignId)); } if (string.IsNullOrEmpty(model.ReferralId)) { throw new ArgumentNullException(nameof(model.ReferralId)); } if (model.Amount <= 0) { return(ReferralStakeRequestErrorCode.InvalidAmount); } if (model.WarningPeriodInDays < 0) { return(ReferralStakeRequestErrorCode.InvalidWarningPeriodInDays); } if (model.StakingPeriodInDays <= 0) { return(ReferralStakeRequestErrorCode.InvalidStakingPeriodInDays); } if (model.StakingPeriodInDays <= model.WarningPeriodInDays) { return(ReferralStakeRequestErrorCode.WarningPeriodShouldSmallerThanStakingPeriod); } if (model.ExpirationBurnRatio < 0 || model.ExpirationBurnRatio > 100) { return(ReferralStakeRequestErrorCode.InvalidBurnRatio); } var existingStake = await _referralStakesRepository.GetByReferralIdAsync(model.ReferralId); if (existingStake != null) { return(ReferralStakeRequestErrorCode.StakeAlreadyExist); } var customerProfile = await _customerProfileClient.CustomerProfiles.GetByCustomerIdAsync(model.CustomerId); if (customerProfile.ErrorCode == CustomerProfileErrorCodes.CustomerProfileDoesNotExist) { return(ReferralStakeRequestErrorCode.CustomerDoesNotExist); } var campaign = await _campaignClient.Campaigns.GetByIdAsync(model.CampaignId); if (campaign.ErrorCode == CampaignServiceErrorCodes.EntityNotFound) { return(ReferralStakeRequestErrorCode.CampaignDoesNotExist); } var walletBlockStatus = await _walletManagementClient.Api.GetCustomerWalletBlockStateAsync(model.CustomerId); if (walletBlockStatus.Status == CustomerWalletActivityStatus.Blocked) { return(ReferralStakeRequestErrorCode.CustomerWalletBlocked); } var isCustomerIdValidGuid = Guid.TryParse(model.CustomerId, out var customerIdGuid); if (!isCustomerIdValidGuid) { return(ReferralStakeRequestErrorCode.InvalidCustomerId); } var customerWalletAddress = await _pbfClient.CustomersApi.GetWalletAddress(customerIdGuid); if (customerWalletAddress.Error == CustomerWalletAddressError.CustomerWalletMissing) { return(ReferralStakeRequestErrorCode.CustomerWalletIsMissing); } var balance = await _pbfClient.CustomersApi.GetBalanceAsync(customerIdGuid); if (balance.Total < model.Amount) { return(ReferralStakeRequestErrorCode.NotEnoughBalance); } #endregion model.Status = StakeStatus.TokensReservationStarted; model.Timestamp = DateTime.UtcNow; var encodedData = _blockchainEncodingService.EncodeStakeRequestData(customerWalletAddress.WalletAddress, model.Amount); var blockchainOperationId = await _pbfClient.OperationsApi.AddGenericOperationAsync(new GenericOperationRequest { Data = encodedData, SourceAddress = _settingsService.GetMasterWalletAddress(), TargetAddress = _settingsService.GetTokenContractAddress() }); return(await _transactionRunner.RunWithTransactionAsync(async txContext => { await _referralStakesRepository.AddAsync(model, txContext); await _stakesBlockchainDataRepository.UpsertAsync(model.ReferralId, blockchainOperationId.OperationId.ToString(), txContext); return ReferralStakeRequestErrorCode.None; })); }