public async Task <ActionResult> Create(string currency, string returnUrl) { var user = await UserManager.FindValidByIdAsync(User.Identity.GetUserId()); var currencyData = await CurrencyReader.GetCurrency(currency); if (currencyData == null || user == null) { ViewBag.Message = $"Currency {currency} not found."; return(View("Error")); } if (currencyData.Status == CurrencyStatus.Maintenance || currencyData.Status == CurrencyStatus.Offline) { ViewBag.HideSupportLink = true; ViewBag.SubTitle = $"Status: {currencyData.Status}"; ViewBag.Message = $"Unfortunately we are unable to process your withdrawal at this time.<br /><br />Status: {currencyData.Status}<br />Reason: {(string.IsNullOrEmpty(currencyData.StatusMessage) ? "Unknown" : currencyData.StatusMessage)}"; return(View("Error")); } if (currencyData.CurrencyId == Constant.NZDT_ID && !UserVerificationReader.IsVerified(user.VerificationLevel)) { return(View("NotVerified")); } return(View(await CreateWithdrawModel(user, new WithdrawCurrencyModel { Name = currencyData.Name, Symbol = currencyData.Symbol, ReturnUrl = GetLocalReturnUrl(returnUrl) }))); }
public async Task <ActionResult> Create(WithdrawCurrencyModel model) { var currencyData = await CurrencyReader.GetCurrency(model.Symbol); var user = await UserManager.FindValidByIdAsync(User.Identity.GetUserId()); if (currencyData == null || user == null) { ViewBag.Message = $"Currency {model.Symbol} not found."; return(View("Error")); } if (currencyData.CurrencyId == Constant.NZDT_ID && !UserVerificationReader.IsVerified(user.VerificationLevel)) { return(View("NotVerified")); } // Verify Address var address = model.AddressData?.Trim(); if (string.IsNullOrEmpty(address)) { address = model.SelectedAddress; } else if (currencyData.AddressType != AddressType.Standard) { if (currencyData.AddressType == AddressType.PaymentId && !CurrencyExtensions.IsValidPaymentId(model.AddressData2?.Trim())) { ModelState.AddModelError("AddressData2", $"Please enter a valid Cryptonote PaymentId."); return(View(await CreateWithdrawModel(user, model))); } address = $"{model.AddressData?.Trim()}:{model.AddressData2?.Trim()}"; if (currencyData.Type == CurrencyType.Fiat) { address = address.TrimEnd(':'); } } if (string.IsNullOrEmpty(address)) { ModelState.AddModelError(user.IsUnsafeWithdrawEnabled ? "AddressData" : "AddressBookError", $"Please enter a valid {model.Symbol} address"); return(View(await CreateWithdrawModel(user, model))); } // Verify Amount var withdrawAmount = decimal.Round(model.Amount, currencyData.CurrencyDecimals); if (withdrawAmount < currencyData.WithdrawMin || withdrawAmount >= currencyData.WithdrawMax) { ModelState.AddModelError("Amount", $"Withdrawal amount must be between {currencyData.WithdrawMin} {currencyData.Symbol} and {currencyData.WithdrawMax} {currencyData.Symbol}"); return(View(await CreateWithdrawModel(user, model))); } // Verify Two Factor if (!await UserManager.VerifyUserTwoFactorCodeAsync(TwoFactorComponent.Withdraw, user.Id, model.Code1, model.Code2)) { ModelState.AddModelError("TwoFactorError", "The TFA code entered was incorrect or has expired, please try again."); return(View(await CreateWithdrawModel(user, model))); } // Create withdraw var twoFactortoken = await GenerateUserTwoFactorTokenAsync(TwoFactorTokenType.WithdrawConfirm, user.Id); var result = await WithdrawWriter.CreateWithdraw(User.Identity.GetUserId(), new CreateWithdrawModel { Address = address, Amount = withdrawAmount, CurrencyId = model.CurrencyId, TwoFactorToken = twoFactortoken, Type = WithdrawType.Normal, }); if (!result.Success) { ModelState.AddModelError("Error", result.Message); return(View(await CreateWithdrawModel(user, model))); } // Send Confirmation email if (!user.DisableWithdrawEmailConfirmation) { await SendConfirmationEmail(user, model.Symbol, withdrawAmount - model.Fee, address, result.Result, twoFactortoken, currencyData.AddressType); } return(RedirectToAction("Summary", new { withdrawId = result.Result, returnUrl = GetLocalReturnUrl(model.ReturnUrl) })); }
public async Task <ApiSubmitUserWithdrawResponse> SubmitUserWithdraw(ApiSubmitUserWithdrawRequest request) { var currency = request.CurrencyId.HasValue ? await CurrencyReader.GetCurrency(request.CurrencyId.Value).ConfigureAwait(false) : await CurrencyReader.GetCurrency(request.Currency).ConfigureAwait(false); if (currency == null) { return new ApiSubmitUserWithdrawResponse { Success = false, Error = "Currency not found." } } ; if (currency.Status == CurrencyStatus.Maintenance || currency.Status == CurrencyStatus.Offline || currency.Status == CurrencyStatus.NoConnections) { return new ApiSubmitUserWithdrawResponse { Success = false, Error = $"Currency is currently not available for withdraw, Status: {currency.Status}" } } ; if (request.Amount < currency.WithdrawMin) { return new ApiSubmitUserWithdrawResponse { Success = false, Error = $"Withdraw amount is below the minimum, Minimum: {currency.WithdrawMin:F8} {currency.Symbol}" } } ; if (request.Amount > currency.WithdrawMax) { return new ApiSubmitUserWithdrawResponse { Success = false, Error = $"Withdraw amount is above the maximum, Maximum: {currency.WithdrawMax:F8} {currency.Symbol}" } } ; var balance = await UserBalanceReader.GetBalance(request.UserId.ToString(), currency.CurrencyId).ConfigureAwait(false); if (balance == null || request.Amount > balance.Available) { return new ApiSubmitUserWithdrawResponse { Success = false, Error = "Insufficient funds." } } ; var user = await UserReader.GetUserById(request.UserId.ToString()).ConfigureAwait(false); if (user == null || !user.IsApiWithdrawEnabled) { return new ApiSubmitUserWithdrawResponse { Success = false, Error = "Your API withdraw setting is currently disabled." } } ; var address = request.Address; if (currency.AddressType != AddressType.Standard) { address = $"{request.Address}:{request.PaymentId ?? string.Empty}"; } if (currency.Type == CurrencyType.Fiat) { address = address.TrimEnd(':'); } if (!user.IsApiUnsafeWithdrawEnabled) { using (var context = ExchangeDataContextFactory.CreateReadOnlyContext()) { var validAddress = await context.AddressBook .AsNoTracking() .FirstOrDefaultAsync(x => x.UserId == request.UserId && x.CurrencyId == currency.CurrencyId && x.Address == address && x.IsEnabled).ConfigureAwait(false); if (validAddress == null) { return new ApiSubmitUserWithdrawResponse { Success = false, Error = $"Address does not exist in your secure Withdraw Address Book" } } ; } } else { if (currency.CurrencyId == Constant.NZDT_ID && !UserVerificationReader.IsVerified(user.VerificationLevel)) { return(new ApiSubmitUserWithdrawResponse { Success = false, Error = $"Id verification required for NZDT services." }); } if (!await DepositService.ValidateAddress(currency.CurrencyId, address)) { return new ApiSubmitUserWithdrawResponse { Success = false, Error = $"Invalid {currency.Symbol} address." } } ; } var response = await TradeService.CreateWithdraw(request.UserId.ToString(), new CreateWithdrawModel { Address = address, Amount = Math.Max(0, request.Amount), CurrencyId = balance.CurrencyId, TwoFactorToken = string.Empty, Type = WithdrawType.Normal }, true).ConfigureAwait(false); if (response.IsError) { return new ApiSubmitUserWithdrawResponse { Success = false, Error = response.Error } } ; return(new ApiSubmitUserWithdrawResponse { Success = true, Data = response.WithdrawId }); }