public CampaignSettingsHistoryItemEntity(ICampaignSettings campaignSettings, string username) { TransactionQueueSasUrl = campaignSettings.TransactionQueueSasUrl; EmailBlackList = campaignSettings.EmailBlackList; Smtp = campaignSettings.Smtp; Username = username; }
private async Task<bool> IsTxValid(TransactionMessage msg, ICampaignSettings settings, decimal soldTokensAmount) { var preSalePhase = settings.IsPreSale(msg.CreatedUtc); var crowdSalePhase = settings.IsCrowdSale(msg.CreatedUtc); var amountInvestedUsd = await GetInvestedUsdAmount(); if (!preSalePhase && !crowdSalePhase) { await _log.WriteInfoAsync(nameof(Process), $"msg: {msg}, settings: {settings.ToJson()}", $"Transaction is out of campaign dates"); await _investorRefundRepository.SaveAsync(msg.Email, InvestorRefundReason.OutOfDates, msg.ToJson()); return false; } if (preSalePhase && soldTokensAmount > settings.PreSaleTotalTokensAmount) { await _log.WriteInfoAsync(nameof(Process), $"soldTokensAmount: {soldTokensAmount}, settings: {settings.ToJson()}, msg: {msg.ToJson()}", $"All presale tokens were sold out"); await _investorRefundRepository.SaveAsync(msg.Email, InvestorRefundReason.PreSaleTokensSoldOut, msg.ToJson()); return false; } if (crowdSalePhase && soldTokensAmount > settings.GetTotalTokensAmount()) { await _log.WriteInfoAsync(nameof(Process), $"soldTokensAmount: {soldTokensAmount}, totalTokensAmount: {settings.GetTotalTokensAmount()}, " + $"settings: {settings.ToJson()}, msg: {msg.ToJson()}", $"All tokens were sold out"); await _investorRefundRepository.SaveAsync(msg.Email, InvestorRefundReason.TokensSoldOut, msg.ToJson()); return false; } if (crowdSalePhase && amountInvestedUsd > settings.HardCapUsd) { await _log.WriteInfoAsync(nameof(Process), $"amountInvestedUsd: {amountInvestedUsd}, hardCapUsd: {settings.HardCapUsd}, " + $"settings: {settings.ToJson()}, msg: {msg.ToJson()}", $"HardCapUsd was exceeded"); await _investorRefundRepository.SaveAsync(msg.Email, InvestorRefundReason.HardCapUsdExceeded, msg.ToJson()); return false; } return true; }
public override void FixtureSetup() { base.FixtureSetup(); _campaignSettingsService = MerchelloContext.Current.Services.CampaignSettingsService; var allSettings = _campaignSettingsService.GetAll(); _campaignSettingsService.Delete(allSettings); _campaignSettings = _campaignSettingsService.CreateCampaignSettingsWithKey("Campaign 1", "campaign1"); }
public static CampaignSettingsModel Create(ICampaignSettings settings) { if (settings == null) { return(null); } return(new CampaignSettingsModel { TransactionQueueSasUrl = settings.TransactionQueueSasUrl, EmailBlackList = settings.EmailBlackList, Smtp = settings.Smtp }); }
private async Task UpdateInvestorReferralCode(InvestorTransaction tx, ICampaignSettings settings) { try { if (settings.EnableReferralProgram) { var investor = await _investorRepository.GetAsync(tx.Email); if (string.IsNullOrEmpty(investor.ReferralCode) && investor.AmountUsd >= settings.MinInvestAmountUsd) { if (!settings.ReferralCodeLength.HasValue) { throw new Exception("settings.ReferralCodeLength does not have value"); } var code = await _referralCodeService.GetReferralCode(settings.ReferralCodeLength.Value); await _investorRepository.SaveReferralCode(investor.Email, code); await _investorAttributeRepository.SaveAsync(InvestorAttributeType.ReferralCode, investor.Email, code); await _log.WriteInfoAsync(nameof(UpdateInvestorReferralCode), $"email: {investor.Email}, code: {code}", $"Update investor referral code"); } if (!string.IsNullOrEmpty(investor.ReferralCodeApplied) && investor.AmountUsd >= settings.MinInvestAmountUsd) { var referralOwnerEmail = await _investorAttributeRepository.GetInvestorEmailAsync( InvestorAttributeType.ReferralCode, investor.ReferralCodeApplied); if (referralOwnerEmail != null) { await _investorRepository.IncrementReferrals(referralOwnerEmail); await _log.WriteInfoAsync(nameof(UpdateInvestorReferralCode), $"referralEmail: {referralOwnerEmail}", $"Increment referrals number"); } } } } catch (Exception ex) { await _log.WriteErrorAsync(nameof(UpdateInvestorReferralCode), $"Tx: {tx.ToJson()}, settings: {settings.ToJson()}", ex); } }
private async Task<InvestorTransaction> SaveTransaction(TransactionMessage msg, ICampaignSettings settings, decimal soldTokensAmount) { var investor = await _investorRepository.GetAsync(msg.Email); var exchangeRate = await GetExchangeRate(msg); var avgExchangeRate = Convert.ToDecimal(exchangeRate.AverageRate); var amountUsd = msg.Amount * avgExchangeRate; var tokenPriceList = TokenPrice.GetPriceList(settings, investor, msg.CreatedUtc, amountUsd, soldTokensAmount); var amountToken = tokenPriceList.Sum(p => p.Count); var tokenPrice = tokenPriceList.Count == 1 ? tokenPriceList[0].Price : (amountUsd / amountToken); var tx = new InvestorTransaction { Email = msg.Email, UniqueId = msg.UniqueId, CreatedUtc = msg.CreatedUtc, Currency = msg.Currency, TransactionId = msg.TransactionId, BlockId = msg.BlockId, PayInAddress = msg.PayInAddress, Amount = msg.Amount, AmountUsd = amountUsd, AmountToken = amountToken, Fee = msg.Fee, TokenPrice = tokenPrice, TokenPriceContext = tokenPriceList.ToJson(), ExchangeRate = avgExchangeRate, ExchangeRateContext = exchangeRate.Rates.ToJson() }; await _log.WriteInfoAsync(nameof(SaveTransaction), $"tx: {tx.ToJson()}", $"Save transaction"); await _investorTransactionRepository.SaveAsync(tx); return tx; }
public async Task UpsertAsync(string campaignId, ICampaignSettings campaignSettings, string username) { var partitionKey = GetPartitionKey(campaignId); var rowKey = GetRowKey(); var entity = new CampaignSettingsEntity(campaignSettings) { PartitionKey = partitionKey, RowKey = rowKey }; await _table.InsertOrReplaceAsync(entity); _cache.Set(CacheKey(campaignId), entity); var historyPartitionKey = GetHistoryPartitionKey(campaignId); var historyRowKey = GetHistoryRowKey(DateTime.UtcNow); var historyEntity = new CampaignSettingsHistoryItemEntity(campaignSettings, username) { PartitionKey = historyPartitionKey, RowKey = historyRowKey }; await _history.InsertAsync(historyEntity); }
public DemoOptinProcessService(IServiceClientFactory serviceClientFactory, ICacheService cacheService, ICampaignSettings campaignConfig, IAuthenticationService authenticationService) : base(serviceClientFactory, cacheService, campaignConfig, authenticationService) { }
public CampaignToken(ICampaignSettings campaignSettings) { _campaignSettings = campaignSettings; _tokenDateTime = DateTime.MinValue; }
public MailingImpl(IAuthenticationService authenticationService, ICampaignSettings campaignSettings) { _authenticationService = authenticationService; _campaignSettings = campaignSettings; }
private TransactionService Init(string investorEmail = "*****@*****.**", double exchangeRate = 1.0) { _log = new LogToMemory(); _campaignInfoRepository = new Mock <ICampaignInfoRepository>(); _campaignInfoRepository .Setup(m => m.IncrementValue(It.Is <CampaignInfoType>(t => t == CampaignInfoType.AmountInvestedUsd), It.IsAny <decimal>())) .Callback((CampaignInfoType t, decimal v) => _usdAmount += v) .Returns(() => Task.CompletedTask); _campaignInfoRepository .Setup(m => m.SaveLatestTransactionsAsync(It.IsAny <string>(), It.IsAny <string>())) .Returns(() => Task.CompletedTask); _campaignSettings = new CampaignSettings { PreSaleStartDateTimeUtc = DateTime.UtcNow.AddDays(-15), PreSaleEndDateTimeUtc = DateTime.UtcNow, PreSaleTotalTokensAmount = 100000000, CrowdSaleStartDateTimeUtc = DateTime.UtcNow, CrowdSaleEndDateTimeUtc = DateTime.UtcNow.AddDays(21), CrowdSaleTotalTokensAmount = 360000000, TokenDecimals = 4, MinInvestAmountUsd = 1000, TokenBasePriceUsd = 0.064M, HardCapUsd = 1000000, EnableReferralProgram = true, ReferralCodeLength = 6 }; _campaignSettingsRepository = new Mock <ICampaignSettingsRepository>(); _campaignSettingsRepository .Setup(m => m.GetAsync()) .Returns(() => Task.FromResult(_campaignSettings)); _exRateClient = new Mock <IIcoExRateClient>(); _exRateClient .Setup(m => m.GetAverageRate(It.IsAny <Pair>(), It.IsAny <DateTime>())) .Returns(() => Task.FromResult(new AverageRateResponse { AverageRate = exchangeRate })); _investor = new Investor() { Email = investorEmail, ConfirmationToken = Guid.NewGuid(), AmountUsd = _campaignSettings.MinInvestAmountUsd + 10 }; _investorRepository = new Mock <IInvestorRepository>(); _investorRepository .Setup(m => m.GetAsync(It.Is <string>(v => !string.IsNullOrWhiteSpace(v) && v == investorEmail))) .Returns(() => Task.FromResult(_investor)); _investorRepository .Setup(m => m.SaveReferralCode(It.IsAny <string>(), It.IsAny <string>())) .Returns(() => Task.CompletedTask); _investorAttributeRepository = new Mock <IInvestorAttributeRepository>(); _investorAttributeRepository .Setup(m => m.SaveAsync(It.IsAny <InvestorAttributeType>(), It.IsAny <string>(), It.IsAny <string>())) .Returns(() => Task.CompletedTask); _investorAttributeRepository .Setup(m => m.GetInvestorEmailAsync( It.IsIn(new InvestorAttributeType[] { InvestorAttributeType.PayInBtcAddress, InvestorAttributeType.PayInEthAddress }), It.IsAny <string>())) .Returns(() => Task.FromResult(investorEmail)); _investorAttributeRepository .Setup(m => m.GetInvestorEmailAsync( It.IsIn(new InvestorAttributeType[] { InvestorAttributeType.ReferralCode }), It.IsAny <string>())) .Returns(() => Task.FromResult("")); _privateInvestorAttributeRepository = new Mock <IPrivateInvestorAttributeRepository>(); _privateInvestorAttributeRepository .Setup(m => m.GetInvestorEmailAsync( It.IsIn(new PrivateInvestorAttributeType[] { PrivateInvestorAttributeType.ReferralCode }), It.IsAny <string>())) .Returns(() => Task.FromResult("")); _investorTransaction = new InvestorTransaction { }; _investorTransactionRepository = new Mock <IInvestorTransactionRepository>(); _investorTransactionRepository .Setup(m => m.GetAsync( It.Is <string>(v => !string.IsNullOrWhiteSpace(v) && v == "*****@*****.**"), It.IsAny <string>())) .Returns(() => Task.FromResult(_investorTransaction)); _investorTransactionRepository .Setup(m => m.SaveAsync(It.IsAny <IInvestorTransaction>())) .Returns(() => Task.CompletedTask); _investorRefundRepository = new Mock <IInvestorRefundRepository>(); _investorRefundRepository .Setup(m => m.SaveAsync(It.IsAny <string>(), It.IsAny <InvestorRefundReason>(), It.IsAny <string>())) .Returns(() => Task.CompletedTask); _investmentMailSender = new Mock <IQueuePublisher <InvestorNewTransactionMessage> >(); _investmentMailSender .Setup(m => m.SendAsync(It.IsAny <InvestorNewTransactionMessage>())) .Returns(() => Task.CompletedTask); _urlEncryptionService = new UrlEncryptionService("E546C8DF278CD5931069B522E695D4F2", "1234567890123456"); _kycService = new KycService(_campaignSettingsRepository.Object, _urlEncryptionService); _referralCodeService = new ReferralCodeService(_investorAttributeRepository.Object, _privateInvestorAttributeRepository.Object); return(new TransactionService( _log, _exRateClient.Object, _investorAttributeRepository.Object, _campaignInfoRepository.Object, _campaignSettingsRepository.Object, _investorTransactionRepository.Object, _investorRefundRepository.Object, _investorRepository.Object, _investmentMailSender.Object, _kycService, _referralCodeService, "http://test-ito.valid.global/summary/{token}/overview")); }
public static IList <TokenPrice> GetPriceList(ICampaignSettings settings, IInvestor investor, DateTime txDateTimeUtc, decimal amountUsd, decimal currentTotal) { var tokenInfo = settings.GetTokenInfo(currentTotal, txDateTimeUtc); if (tokenInfo == null) { return(null); } var priceList = new List <TokenPrice>(); var tokenPhase = Enum.GetName(typeof(TokenPricePhase), tokenInfo.Phase); var tokens = (amountUsd / tokenInfo.Price).RoundDown(settings.TokenDecimals); if (tokenInfo.Phase == TokenPricePhase.CrowdSaleInitial) { var tokensBelow = Consts.CrowdSale.InitialAmount - currentTotal; if (tokensBelow > 0M) { if (tokens > tokensBelow) { // tokens below threshold priceList.Add(new TokenPrice(tokensBelow, tokenInfo.Price, tokenPhase)); // tokens above threshold var amountUsdAbove = amountUsd - (tokensBelow * tokenInfo.Price); var priceAbove = settings.GetTokenPrice(TokenPricePhase.CrowdSaleFirstDay); var tokensAbove = (amountUsdAbove / priceAbove).RoundDown(settings.TokenDecimals); priceList.Add(new TokenPrice(tokensAbove, priceAbove, nameof(TokenPricePhase.CrowdSaleFirstDay))); return(priceList); } } } if (settings.EnableReferralProgram && (tokenInfo.Phase == TokenPricePhase.CrowdSaleSecondWeek || tokenInfo.Phase == TokenPricePhase.CrowdSaleLastWeek)) { if (settings.ReferralDiscount.HasValue && !string.IsNullOrEmpty(investor.ReferralCodeApplied)) { var tokenPriceReferral = settings.TokenBasePriceUsd * ((100 - settings.ReferralDiscount.Value) / 100); var takenPhaseReferral = "ReferralDiscount"; var tokensReferral = (amountUsd / tokenPriceReferral).RoundDown(settings.TokenDecimals); priceList.Add(new TokenPrice(tokensReferral, tokenPriceReferral, takenPhaseReferral)); return(priceList); } if (settings.ReferralOwnerDiscount.HasValue && investor.ReferralsNumber > 0) { var tokenPriceReferral = settings.TokenBasePriceUsd * ((100 - settings.ReferralOwnerDiscount.Value) / 100); var takenPhaseReferral = "ReferralOwnerDiscount"; var tokensReferral = (amountUsd / tokenPriceReferral).RoundDown(settings.TokenDecimals); priceList.Add(new TokenPrice(tokensReferral, tokenPriceReferral, takenPhaseReferral)); return(priceList); } } priceList.Add(new TokenPrice(tokens, tokenInfo.Price, tokenPhase)); return(priceList); }
public CampaignToken(IAuthenticationService authenticationService, ICampaignSettings campaignSettings) { _authenticationService = authenticationService; _campaignSettings = campaignSettings; }
public CampaignSettingsEntity(ICampaignSettings campaignSettings) { TransactionQueueSasUrl = campaignSettings.TransactionQueueSasUrl; EmailBlackList = campaignSettings.EmailBlackList; Smtp = campaignSettings.Smtp; }
public ExtendedRecipientListService(IServiceClientFactory serviceClientFactory, IAuthenticationService authenticationService, ICacheService cacheService, ICampaignSettings campaignConfig) : base(serviceClientFactory, authenticationService, cacheService, campaignConfig) { }
private async Task SendConfirmationEmail(InvestorTransaction tx, string link, ICampaignSettings settings) { try { var investor = await _investorRepository.GetAsync(tx.Email); var message = new InvestorNewTransactionMessage { EmailTo = tx.Email, InvestedAmountUsd = investor.AmountUsd.RoundDown(2), InvestedAmountToken = investor.AmountToken.RoundDown(4), TransactionAmount = tx.Amount, TransactionAmountUsd = tx.AmountUsd.RoundDown(2), TransactionAmountToken = tx.AmountToken.RoundDown(4), TransactionFee = tx.Fee, TransactionAsset = tx.Currency.ToAssetName(), LinkToSummaryPage = _siteSummaryPageUrl.Replace("{token}", investor.ConfirmationToken.Value.ToString()), LinkTransactionDetails = link, MinAmount = settings.MinInvestAmountUsd, MoreInvestmentRequired = investor.AmountUsd < settings.MinInvestAmountUsd }; if (settings.KycEnableRequestSending && investor.KycRequestedUtc == null && investor.AmountUsd >= settings.MinInvestAmountUsd) { var kycId = await SaveInvestorKyc(investor.Email); var kycLink = await _kycService.GetKycLink(tx.Email, kycId); message.KycRequired = true; message.KycLink = kycLink; } await _log.WriteInfoAsync(nameof(SendConfirmationEmail), $"message: {message.ToJson()}", $"Send transaction confirmation message to queue"); await _investmentMailSender.SendAsync(message); } catch (Exception ex) { await _log.WriteErrorAsync(nameof(SendConfirmationEmail), $"Tx: {tx.ToJson()}, TxLink: {link}", ex); } }