Example #1
0
        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();
            }
        }
Example #2
0
        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
            });
        }
Example #4
0
        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);
        }
Example #5
0
        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();
            }
        }
Example #6
0
        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);
        }