public async Task ProcessPayment(Guid userId, decimal amount, WalletTransactionType type) { if (type != WalletTransactionType.ServiceFee) { throw new NotImplementedException(); } using (var transaction = await context.Database.BeginTransactionAsync()) { var wallet = await context.Wallets.FirstOrDefaultAsync(w => w.UserId == userId && w.Currency == Currency.SPX); if (wallet == null) { wallet = new Wallet() { UserId = userId, Amount = 0, Currency = Currency.SPX, }; context.Wallets.Add(wallet); await context.SaveChangesAsync(); } context.Add(new WalletTransaction { Id = Guid.NewGuid(), Amount = amount, DateCreated = DateTime.UtcNow, Currency = wallet.Currency, Type = type, Status = WalletTransactionStatus.Compleated, Wallet = wallet, WalletId = wallet.Id }); wallet.Amount += amount; await context.SaveChangesAsync(); transaction.Commit(); } }
public async Task <ApiSecretInfo> Generate(Guid userId) { var apiKey = new UserApiKey() { DateCreated = DateTime.UtcNow, IsActive = true, ApiKey = RandomUtils.GetRandomString(32), ApiSecret = RandomUtils.GetRandomString(64), UserId = userId }; context.UserApiKeys.Add(apiKey); await context.SaveChangesAsync(); return(new ApiSecretInfo() { ApiKey = apiKey.ApiKey, ApiSecret = apiKey.ApiSecret, IsActive = apiKey.IsActive }); }
public async Task <WalletInfo> GenerateAddress(Currency currency, Guid userId) { logger.LogInformation("Start {Method} {Currency} {UserId}", nameof(GenerateAddress), currency, userId); NewWalletAddress result = null; //var customKey = CreateKey(userId); try { result = await addressService.GenerateAddress(currency); } catch (Exception e) { logger.LogWarning("Wallet was not created {Method} {UserId} {Exception}", nameof(GenerateAddress), userId, e.ToString()); logger.LogError("Wallet was not created {Method} {UserId} {Exception}", nameof(GenerateAddress), userId, e.ToString()); } if (result == null) { logger.LogError("Wallet was not created {Method} {UserId}", nameof(GenerateAddress), userId); //TODO: Try to use another gateway? return(null); } var blockchainAddress = new BlockchainAddress() { Type = BlockchainAddressType.Deposit, DateCreated = DateTime.UtcNow, GatewayCode = defaultGatewayCode, Address = result.Address, VerificationCode = result.VerificationCode, UserId = userId, IsActive = true, Currency = currency }; context.BlockchainAddresses.Add(blockchainAddress); await context.SaveChangesAsync(); logger.LogInformation("Wallet created {WalletId};Address:{Address};UserId:{UserId}", blockchainAddress.Id, result.Address, blockchainAddress.UserId); return(new WalletInfo() { WalletId = blockchainAddress.Id, Address = blockchainAddress.Address, Currency = blockchainAddress.Currency }); }
public async Task <(Guid requestId, string withdrawalCode)> CreateWithdrawalRequest(CreateWithdrawalRequestModel model) { logger.LogInformation($"{model} Starting..."); decimal amountCommission = 1m; var finalAmount = model.Amount - amountCommission; if (model.Amount <= 0 || finalAmount <= 0) { throw new ArgumentException("ErrorAmountMustBeGreaterZero"); } var wallet = await context.Wallets.FirstAsync(x => x.Currency == model.Currency && x.UserId == model.UserId); if (wallet.Amount < model.Amount) { throw new ArgumentException("ErrorNotEnoughMoney"); } if (wallet.Currency != Currency.SPX) { throw new ArgumentException($"Withdrawal requests from {wallet.Currency} not allowed"); } wallet.Amount -= model.Amount; var code = new PasswordGenerator(20).IncludeLowercase().IncludeUppercase().IncludeNumeric().Next(); var walletTransaction = new WalletTransaction { Id = Guid.NewGuid(), Amount = model.Amount, DateCreated = DateTime.UtcNow, Currency = Currency.SPX, Type = WalletTransactionType.WalletWithdraw, WithdrawAddress = model.Wallet, Status = WalletTransactionStatus.New, Wallet = wallet, }; context.Add(walletTransaction); var request = new WithdrawalRequest { Id = Guid.NewGuid(), Amount = model.Amount, AmountWithCommission = finalAmount, Currency = model.Currency, UserId = model.UserId, Status = WithdrawalRequestStatus.New, Wallet = model.Wallet, Code = code, DateCreate = DateTime.UtcNow, IsApprovedByManager = false, IsApprovedByUser = false, WalletTransactionId = walletTransaction.Id }; context.Add(request); await context.SaveChangesAsync(); return(request.Id, code); }
public static async Task SeedAsync(Sp8deDbContext context) { var userId = Guid.Parse("c8665ddd-5297-4cb7-b0a8-aa27c94bb8cc"); if (!context.UserApiKeys.Any()) { context.UserApiKeys.Add(new UserApiKey() { DateCreated = DateTime.UtcNow, ApiKey = string.Join("", Enumerable.Repeat("X", 32)), ApiSecret = string.Join("", Enumerable.Repeat("Y", 64)), IsActive = true, UserId = userId, Name = "DemoUser", Limit = 1000000 }); await context.SaveChangesAsync(); } if (!context.Wallets.Any()) { context.Wallets.Add(new Wallet() { Id = Guid.NewGuid(), UserId = userId, Currency = Common.Enums.Currency.SPX, Amount = 1000000 }); await context.SaveChangesAsync(); } if (!context.BlockchainAddresses.Any()) { context.BlockchainAddresses.Add(new BlockchainAddress() { Address = "0x6a43ece9026a36c5498d740a4b06bb25391d4bde", Currency = Common.Enums.Currency.SPX, DateCreated = DateTime.UtcNow, IsActive = true, GatewayCode = "SPAY", Type = Common.Enums.BlockchainAddressType.Deposit, Id = Guid.NewGuid(), UserId = userId }); await context.SaveChangesAsync(); } if (!context.BlockchainTransactions.Any()) { context.BlockchainTransactions.Add(new BlockchainTransaction() { DateCreated = DateTime.UtcNow, Currency = Common.Enums.Currency.SPX, Type = Common.Enums.BlockchainTransactionType.Deposit, Address = "0x6a43ece9026a36c5498d740a4b06bb25391d4bde", Amount = 110184.03m, Id = Guid.NewGuid(), Hash = "0x3f58561e435317501502ae18d97e206ab2569a9a563d2c83e13524af8a513797", BlockchainAddressId = context.BlockchainAddresses.First(x => x.Address == "0x6a43ece9026a36c5498d740a4b06bb25391d4bde").Id, Status = Common.Enums.BlockchainTransactionStatus.ConfirmedAndValidated }); await context.SaveChangesAsync(); } if (!context.WalletTransactions.Any()) { context.WalletTransactions.Add(new WalletTransaction() { Id = Guid.NewGuid(), Currency = Common.Enums.Currency.SPX, DateCreated = DateTime.UtcNow, Amount = 110184.03m, Status = Common.Enums.WalletTransactionStatus.Compleated, Type = Common.Enums.WalletTransactionType.WalletDeposit, WalletId = context.Wallets.First(x => x.UserId == userId && x.Currency == Common.Enums.Currency.SPX).Id, BlockchainTransactionId = context.BlockchainTransactions.First(x => x.Hash == "0x3f58561e435317501502ae18d97e206ab2569a9a563d2c83e13524af8a513797").Id }); await context.SaveChangesAsync(); } }
public async Task <PaymentTransactionInfo> ProcessCallback(ProcessPaymentTransaction request) { var blockchainAddress = context.BlockchainAddresses.FirstOrDefault(addr => addr.Address == request.Address && addr.Currency == request.Currency); if (blockchainAddress == null) { var msg = $"{request.Currency} address not found - {request.Address}"; logger.LogError(msg); throw new ApplicationException(msg); } if (request.VerificationCode != blockchainAddress.VerificationCode) { var msg = $"Invalid VerificationCode {request.VerificationCode} for {request.Address}"; logger.LogError(msg); throw new ApplicationException(msg); } PaymentTransactionInfo transactionInfo; using (var transaction = await context.Database.BeginTransactionAsync()) { var wallet = context.Wallets.FirstOrDefault(w => w.UserId == blockchainAddress.UserId && w.Currency == blockchainAddress.Currency); if (wallet == null) { wallet = new Wallet() { UserId = blockchainAddress.UserId.Value, Amount = 0, Currency = blockchainAddress.Currency, }; context.Wallets.Add(wallet); context.SaveChanges(); } var blockchainTransaction = context.BlockchainTransactions .FirstOrDefault(t => t.Hash == request.TransactionHash && t.BlockchainAddressId == blockchainAddress.Id); if (blockchainTransaction != null) { if (blockchainTransaction.Status == BlockchainTransactionStatus.Pending || blockchainTransaction.Status == BlockchainTransactionStatus.New) { blockchainTransaction.Status = request.IsConfirmed ? BlockchainTransactionStatus.ConfirmedAndValidated : BlockchainTransactionStatus.Pending; blockchainTransaction.LastUpdated = DateTime.UtcNow; context.Update(blockchainTransaction); if (blockchainTransaction.Status == BlockchainTransactionStatus.ConfirmedAndValidated) { ProcessPayment(wallet, blockchainTransaction); } } else { logger.LogError($"Can not override status from {blockchainTransaction.Status} to {request.IsConfirmed}"); } } else { blockchainTransaction = new BlockchainTransaction { Id = Guid.NewGuid(), Hash = request.TransactionHash, Type = BlockchainTransactionType.Deposit, BlockchainAddressId = blockchainAddress.Id, Amount = request.Amount, //AmountBigInt = request.AmountBigInt,//TODO: Please add as string Currency = request.Currency, Fee = request.Fee, DateCreated = DateTime.UtcNow, Status = request.IsConfirmed ? BlockchainTransactionStatus.ConfirmedAndValidated : BlockchainTransactionStatus.Pending }; context.BlockchainTransactions.Add(blockchainTransaction); if (blockchainTransaction.Status == BlockchainTransactionStatus.ConfirmedAndValidated) { ProcessPayment(wallet, blockchainTransaction); } } await context.SaveChangesAsync(); transaction.Commit(); transactionInfo = new PaymentTransactionInfo { TransactionId = blockchainTransaction.Id, TransactionHash = blockchainTransaction.Hash, Amount = blockchainTransaction.Amount, Currency = request.Currency.ToString(), GatewayCode = request.GatewayCode, Status = blockchainTransaction.Status, IsValid = true }; } return(transactionInfo); }