public async Task <IWriterResult> CreateTermDeposit(string userId, CreateTermDepositModel model) { using (var transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions { IsolationLevel = IsolationLevel.Snapshot }, TransactionScopeAsyncFlowOption.Enabled)) { var currentUser = new Guid(userId); using (var context = ExchangeDataContextFactory.CreateContext()) { var user = await context.Users.FirstOrDefaultAsync(x => x.Id == currentUser).ConfigureAwait(false); if (user == null) { return(new WriterResult <int>(false, "Unauthorized")); } var termDepositItem = await context.TermDepositItem.FirstOrDefaultAsync(x => x.Id == model.Id).ConfigureAwait(false); if (termDepositItem == null) { return(new WriterResult <int>(false, "Invalid term deposit")); } var totalTermDeposit = termDepositItem.MinInvestment * model.Count; var balance = await context.Balance.FirstOrDefaultAsync(x => x.UserId == user.Id && x.CurrencyId == Constant.DOTCOIN_ID).ConfigureAwait(false); if (balance == null || balance.Available < totalTermDeposit) { return(new WriterResult <int>(false, "Insufficient funds for term deposit.")); } var withdrawal = new Entity.Withdraw { Address = termDepositItem.Address, Amount = totalTermDeposit, Confirmations = 0, CurrencyId = Constant.DOTCOIN_ID, Fee = 0, IsApi = false, Status = WithdrawStatus.Pending, TimeStamp = DateTime.UtcNow, TwoFactorToken = string.Empty, Txid = string.Empty, Type = WithdrawType.TermDeposit, UserId = user.Id }; context.Withdraw.Add(withdrawal); await context.SaveChangesAsync().ConfigureAwait(false); await context.AuditUserBalance(user.Id, balance.CurrencyId).ConfigureAwait(false); var termBegin = DateTime.UtcNow; var termEnd = termBegin.AddDays(30 * termDepositItem.TermLength); var nextPayment = termBegin.AddDays(30); var termdeposit = new Entity.TermDeposit { UserId = user.Id, WithdrawId = withdrawal.Id, TermDepositItemId = termDepositItem.Id, Status = TermDepositStatus.Active, TermBegin = termBegin, NextPayout = nextPayment, TermEnd = termEnd, Closed = termEnd }; context.TermDeposit.Add(termdeposit); await context.SaveChangesAsync().ConfigureAwait(false); transactionScope.Complete(); return(new WriterResult(true, $"Successfully created term deposit #{termdeposit.Id}")); } } }
private async Task <IWriterResult <int> > ProcessWithdraw(CreateWithdraw model) { using (var context = DataContextFactory.CreateContext()) { var currency = await context.Currency.FirstOrDefaultAsync(x => x.Id == model.CurrencyId); if (currency == null || !currency.IsEnabled || currency.Status != CurrencyStatus.OK) { return(WriterResult <int> .ErrorResult("Currency not found or is currently disabled.")); } var user = await context.Users.FirstOrDefaultAsync(x => x.Id == model.UserId); if (user == null || !user.IsWithdrawEnabled) { return(WriterResult <int> .ErrorResult("Your withdrawals are currently disabled.")); } var auditResult = await AuditService.AuditUserCurrency(context, model.UserId, model.CurrencyId); if (!auditResult.Success || model.Amount > auditResult.Avaliable) { return(WriterResult <int> .ErrorResult("Insufficient funds.")); } if (model.Amount < currency.MinWithdraw || model.Amount > currency.MaxWithdraw) { return(WriterResult <int> .ErrorResult("Withdrawal amount must be between {0} and {1} {2}", currency.MinWithdraw, currency.MaxWithdraw, currency.Symbol)); } var isValidAddress = await WalletService.ValidateAddress(model.Address, currency.WalletHost, currency.WalletPort, currency.WalletUser, currency.WalletPass); if (!isValidAddress) { return(WriterResult <int> .ErrorResult($"Invalid {currency.Symbol} address.")); } var newWithdraw = new Entity.Withdraw { IsApi = model.IsApi, TimeStamp = DateTime.UtcNow, TwoFactorToken = model.ConfirmationToken, Address = model.Address, CurrencyId = model.CurrencyId, Amount = Math.Max(0, model.Amount), Fee = currency.WithdrawFee, WithdrawType = WithdrawType.Normal, WithdrawStatus = model.IsApi ? WithdrawStatus.Pending : WithdrawStatus.Unconfirmed, UserId = model.UserId }; context.Withdraw.Add(newWithdraw); await context.SaveChangesAsync(); await AuditService.AuditUserCurrency(context, model.UserId, model.CurrencyId); return(WriterResult <int> .SuccessResult(newWithdraw.Id)); } }