public Withdrawal GenerateWithdrawal(string contractAddress) { PensionFund pensionFund = PensionFundBusiness.GetByContract(contractAddress); SmartContract smartContract = SmartContractBusiness.GetDefaultDemonstrationPensionFund(); List <PensionFundTransaction> transactions = Data.List(pensionFund.Option.PensionFundContract.TransactionHash); if (transactions.Any(c => !c.BlockNumber.HasValue)) { throw new InvalidOperationException("Wait for unfinished transactions."); } else if (transactions.Any(c => c.FunctionType == FunctionType.CompleteWithdrawal)) { throw new InvalidOperationException("Withdrawal already made."); } PensionFundTransaction withdrawalTransaction = CreateTransaction(DateTime.UtcNow, FunctionType.CompleteWithdrawal, pensionFund.Option.Company.Employee.Address, pensionFund.Option.PensionFundContract.TransactionHash); withdrawalTransaction = GenerateContractTransaction(withdrawalTransaction, pensionFund.Option.Company.Employee.Address, pensionFund.Option.PensionFundContract.Address, smartContract.ABI, smartContract.ContractFunctions.Single(c => c.FunctionType == FunctionType.CompleteWithdrawal).GasLimit, 0); return(new Withdrawal() { TransactionHash = withdrawalTransaction.TransactionHash, CreatedDate = withdrawalTransaction.CreationDate, Responsable = withdrawalTransaction.WalletAddress }); }
public PensionFundContract CheckContractCreationTransaction(String transactionHash) { var pensionFundContract = Data.GetPensionFundContract(transactionHash); if (pensionFundContract == null) { throw new ArgumentException("Invalid transaction hash."); } Transaction demoContractTransaction = EthereumManager.GetTransaction(transactionHash); if (demoContractTransaction == null) { if (pensionFundContract.CreationDate < DateTime.UtcNow.AddMinutes(PensionFundTransactionBusiness.BLOCKCHAIN_TRANSACTION_TOLERANCE)) { PoolInfo poolInfo = GetPoolInfo(); if (!poolInfo.Pending.Contains(pensionFundContract.TransactionHash)) { Logger.LogError(string.Format("Transaction for creation contract {0} is lost.", pensionFundContract.TransactionHash)); List <PensionFundReferenceContract> referenceDistribution = PensionFundReferenceContractBusiness.List(pensionFundContract.TransactionHash); if (!referenceDistribution.Any()) { throw new Exception("Reference contract cannot be found."); } PensionFund pensionFund = PensionFundBusiness.GetByTransaction(pensionFundContract.TransactionHash); if (pensionFund == null) { throw new Exception("Pension fund cannot be found."); } pensionFund.Option.Company.BonusDistribution = BonusDistributionBusiness.List(pensionFund.Option.Company.Address); if (!pensionFund.Option.Company.BonusDistribution.Any()) { throw new ArgumentException("Bonus distribution cannot be found."); } PensionFundReferenceContractBusiness.Delete(pensionFundContract.TransactionHash); Delete(pensionFundContract); pensionFundContract = Create(pensionFund.Option.Address, pensionFund.Option.Company.Address, pensionFund.Option.Company.Employee.Address, pensionFund.Option.Fee, pensionFund.Option.LatePenalty, pensionFund.Option.Company.MaxSalaryBonusRate, pensionFund.Option.Company.Employee.Contribution, pensionFund.Option.Company.BonusRate, pensionFund.Option.Company.Employee.Salary, referenceDistribution.ToDictionary(c => c.ReferenceContractAddress, c => c.Percentage), pensionFund.Option.Company.BonusDistribution.ToDictionary(c => c.Period, c => c.ReleasedBonus)); foreach (PensionFundReferenceContract reference in referenceDistribution) { PensionFundReferenceContractBusiness.Create(pensionFundContract.TransactionHash, reference.ReferenceContractAddress, reference.Percentage); } } } return(pensionFundContract); } else { pensionFundContract = UpdateAfterMined(pensionFundContract, demoContractTransaction); } return(pensionFundContract); }
public Withdrawal ReadWithdrawal(string contractAddress) { string cacheKey = string.Format("Withdrawal{0}", contractAddress); Withdrawal cachedWithdrawal = MemoryCache.Get <Withdrawal>(cacheKey); if (cachedWithdrawal != null) { return(cachedWithdrawal); } PensionFund pensionFund = PensionFundBusiness.GetByContract(contractAddress); SmartContract smartContract = SmartContractBusiness.GetDefaultDemonstrationPensionFund(); PensionFundTransaction transaction = Data.List(pensionFund.Option.PensionFundContract.TransactionHash).Where(c => c.FunctionType == FunctionType.CompleteWithdrawal).SingleOrDefault(); if (transaction == null) { return(null); } WithdrawalInfo withdrawalInfo = EthereumManager.ReadWithdrawalFromDefaultPensionFund(contractAddress); PensionFundTransaction[] pendingCreate = string.IsNullOrEmpty(transaction.TransactionHash) ? new PensionFundTransaction[] { transaction } : new PensionFundTransaction[0]; PensionFundTransaction[] pendingComplete = pendingCreate.Length == 0 && !transaction.BlockNumber.HasValue ? new PensionFundTransaction[] { transaction } : new PensionFundTransaction[0]; BaseEventInfo[] withdrawEvent = withdrawalInfo != null ? new BaseEventInfo[] { withdrawalInfo } : new BaseEventInfo[0]; HandleTransactions(smartContract, pensionFund, new PensionFundTransaction[] { }, pendingCreate, pendingComplete, withdrawEvent); Withdrawal withdrawal = null; if (withdrawalInfo != null) { withdrawal = new Withdrawal() { TransactionHash = transaction.TransactionHash, CreatedDate = transaction.CreationDate, Responsable = transaction.WalletAddress, BlockNumber = withdrawalInfo.BlockNumber, Period = withdrawalInfo.Period, EmployeeAbsoluteBonus = withdrawalInfo.EmployeeAbsoluteBonus, EmployeeBonus = withdrawalInfo.EmployeeBonus, EmployeeSzaboCashback = withdrawalInfo.EmployeeSzaboCashback, EmployeeTokenCashback = withdrawalInfo.EmployeeTokenCashback, EmployerSzaboCashback = withdrawalInfo.EmployerSzaboCashback, EmployerTokenCashback = withdrawalInfo.EmployerTokenCashback, ReferenceDate = pensionFund.Option.PensionFundContract.CreationDate.AddMonths(withdrawalInfo.Period).Date }; MemoryCache.Set <Withdrawal>(cacheKey, withdrawal); } else { withdrawal = new Withdrawal() { TransactionHash = transaction.TransactionHash, CreatedDate = transaction.CreationDate, Responsable = transaction.WalletAddress }; } return(withdrawal); }
public Progress ReadPayments(string contractAddress) { PensionFund pensionFund = PensionFundBusiness.GetByContract(contractAddress); string cacheKey = GetCachePaymentKey(contractAddress); List <Payment> cachedPayment = MemoryCache.Get <List <Payment> >(cacheKey); if (cachedPayment != null && cachedPayment.Count == 120) { return(PensionFundBusiness.GetProgress(pensionFund, cachedPayment)); } SmartContract smartContract = SmartContractBusiness.GetDefaultDemonstrationPensionFund(); IEnumerable <PensionFundTransaction> transactions = Data.List(pensionFund.Option.PensionFundContract.TransactionHash). Where(c => c.FunctionType == FunctionType.EmployeeBuy || c.FunctionType == FunctionType.CompanyBuy); IEnumerable <PensionFundTransaction> pendingCreateTransactions = transactions.Where(c => string.IsNullOrEmpty(c.TransactionHash)); IEnumerable <PensionFundTransaction> pendingCompleteTransactions = transactions.Where(c => !c.BlockNumber.HasValue && !string.IsNullOrEmpty(c.TransactionHash)); if (!transactions.Any()) { return(PensionFundBusiness.GetProgress(pensionFund, new List <Payment>())); } else if (cachedPayment != null && cachedPayment.Count == transactions.Count()) { return(PensionFundBusiness.GetProgress(pensionFund, cachedPayment)); } else if (cachedPayment != null && (cachedPayment.Count + pendingCreateTransactions.Count()) == transactions.Count()) { transactions = HandleTransactions(smartContract, pensionFund, transactions, pendingCreateTransactions, pendingCompleteTransactions, new BaseEventInfo[] { }); return(PensionFundBusiness.GetProgress(pensionFund, pendingCreateTransactions.Select(c => new Payment() { CreatedDate = c.CreationDate, Responsable = c.WalletAddress }).Concat(cachedPayment))); } List <BuyInfo> buyEvents = EthereumManager.ReadBuyFromDefaultPensionFund(contractAddress); transactions = HandleTransactions(smartContract, pensionFund, transactions, pendingCreateTransactions, pendingCompleteTransactions, buyEvents.Select(c => new BaseEventInfo() { BlockNumber = c.BlockNumber, TransactionHash = c.TransactionHash })); List <Payment> completedPayments = new List <Payment>(); if (buyEvents.Count > 0) { foreach (PensionFundTransaction trans in transactions) { BuyInfo buyInfo = buyEvents.SingleOrDefault(c => c.TransactionHash == trans.TransactionHash); if (buyInfo != null) { completedPayments.Add(new Payment() { TransactionHash = trans.TransactionHash, CreatedDate = trans.CreationDate, Responsable = trans.WalletAddress, BlockNumber = buyInfo.BlockNumber, Period = buyInfo.Period, AuctusFee = buyInfo.AuctusFee, LatePenalty = buyInfo.LatePenalty, PensionFundFee = buyInfo.PensionFundFee, SzaboInvested = buyInfo.SzaboInvested, TokenAmount = buyInfo.TokenAmount, DaysOverdue = buyInfo.DaysOverdue, ReferenceDate = pensionFund.Option.PensionFundContract.CreationDate.AddMonths(buyInfo.Period).Date }); } } if (completedPayments.Count > 0) { MemoryCache.Set <List <Payment> >(cacheKey, completedPayments); } } IEnumerable <Payment> remainingPayments = transactions.Where(c => string.IsNullOrEmpty(c.TransactionHash) || !completedPayments.Any(l => l.TransactionHash == c.TransactionHash)).Select(c => new Payment() { TransactionHash = c.TransactionHash, CreatedDate = c.CreationDate, Responsable = c.WalletAddress }); return(PensionFundBusiness.GetProgress(pensionFund, remainingPayments.Concat(completedPayments))); }
public Progress GeneratePayment(string contractAddress, int monthsAmount) { if (monthsAmount < 1 || monthsAmount > 60) { throw new InvalidOperationException("Invalid months amount."); } PensionFund pensionFund = PensionFundBusiness.GetByContract(contractAddress); SmartContract smartContract = SmartContractBusiness.GetDefaultDemonstrationPensionFund(); List <PensionFundTransaction> transactions = Data.List(pensionFund.Option.PensionFundContract.TransactionHash); int payments = transactions.Count(c => c.ContractFunctionId == FunctionType.CompanyBuy.Type || c.ContractFunctionId == FunctionType.EmployeeBuy.Type); if (payments == 120) { throw new InvalidOperationException("All payments already been made."); } else if (payments + (monthsAmount * 2) > 120) { throw new InvalidOperationException("Too many payments."); } else if (transactions.Any(c => c.FunctionType == FunctionType.CompleteWithdrawal)) { throw new InvalidOperationException("Withdrawal already made."); } List <PensionFundTransaction> newTransactions = new List <PensionFundTransaction>(); Parallel.For(1, monthsAmount + 1, new ParallelOptions() { MaxDegreeOfParallelism = 5 }, month => { DateTime date = DateTime.UtcNow; newTransactions.Add(CreateTransaction(date, FunctionType.EmployeeBuy, pensionFund.Option.Company.Employee.Address, pensionFund.Option.PensionFundContract.TransactionHash)); newTransactions.Add(CreateTransaction(date, FunctionType.CompanyBuy, pensionFund.Option.Company.Address, pensionFund.Option.PensionFundContract.TransactionHash)); }); GeneratePaymentContractTransaction(newTransactions, pensionFund, smartContract); IEnumerable <Payment> newPayments = newTransactions.Select(c => new Payment() { CreatedDate = c.CreationDate, Responsable = c.WalletAddress }); if (payments == 0) { return(PensionFundBusiness.GetProgress(pensionFund, newPayments.ToList())); } else { List <Payment> cachedPayment = MemoryCache.Get <List <Payment> >(GetCachePaymentKey(contractAddress)); if (cachedPayment != null && cachedPayment.Count == payments) { return(PensionFundBusiness.GetProgress(pensionFund, newPayments.Concat(cachedPayment))); } else { return(ReadPayments(contractAddress)); } } }