/// <summary> /// Created Address with optimistic lock /// </summary> /// <param name="repoQuery"></param> /// <param name="rpcClass"></param> /// <param name="walletId"></param> /// <param name="other"></param> /// <typeparam name="TBlockchainAddress"></typeparam> /// <returns></returns> public virtual async Task <ReturnObject> CreateAddressAsync <TBlockchainAddress>( IAddressRepository <TBlockchainAddress> repoQuery, IBlockchainRpc rpcClass, string walletId, string other = "") where TBlockchainAddress : BlockchainAddress { try { using (var walletRepository = VakapayRepositoryFactory.GetWalletRepository(DbConnection)) { var walletCheck = walletRepository.FindById(walletId); if (walletCheck == null) { return new ReturnObject { Status = Status.STATUS_ERROR, Message = "Wallet Not Found" } } ; } var resultsRPC = rpcClass.CreateNewAddress(other); if (resultsRPC.Status == Status.STATUS_ERROR) { return(resultsRPC); } var address = resultsRPC.Data; // TBlockchainAddress _newAddress = new TBlockchainAddress(); var resultDB = await repoQuery.InsertAddress(address, walletId, other); // //if (result.Status == Status.StatusError) //{ // return new ReturnObject // { // Status = Status.StatusSuccess, // Message = "Cannot Insert Address" // }; //} //update address into wallet db //wallet.WalletBusiness(VakapayRepositoryFactory); return(new ReturnObject { Status = resultDB.Status, Message = resultDB.Message }); } catch (Exception e) { return(new ReturnObject { Status = Status.STATUS_ERROR, Message = e.Message }); } }
/// <summary> /// Created Address with optimistic lock /// </summary> /// <param name="rpcClass"></param> /// <param name="walletId"></param> /// <param name="other"></param> /// <returns></returns> public virtual ReturnObject CreateAddress(IBlockchainRpc rpcClass, string userId, string other = "") { try { using (var dbConnection = SmartContractRepositoryFactory.GetDbConnection()) { if (dbConnection.State != ConnectionState.Open) { dbConnection.Open(); } var userRepository = SmartContractRepositoryFactory.GetUserRepository(dbConnection); var userCheck = userRepository.FindByIdUser(userId); if (userCheck == null) { return new ReturnObject { Status = Status.STATUS_ERROR, Message = "User Not Found" } } ; var resultsRPC = rpcClass.CreateNewAddress(other); if (resultsRPC.Status == Status.STATUS_ERROR) { return(resultsRPC); } var address = resultsRPC.Data; return(new ReturnObject { Status = Status.STATUS_SUCCESS, Data = address, Message = "Can't update wallet " + userCheck.mem_id }); } } catch (Exception e) { return(new ReturnObject { Status = Status.STATUS_ERROR, Message = e.Message }); } }
/// <summary> /// Created Address with optimistic lock /// </summary> /// <param name="repoQuery"></param> /// <param name="rpcClass"></param> /// <param name="walletId"></param> /// <param name="other"></param> /// <typeparam name="TBlockchainAddress"></typeparam> /// <returns></returns> public override async Task <ReturnObject> CreateAddressAsync <TBlockchainAddress>( IAddressRepository <TBlockchainAddress> repoQuery, IBlockchainRpc rpcClass, string walletId, string other = "") { //return base.CreateAddressAsync(wallet, repoQuery, rpcClass, walletId, other); try { using (var walletRepository = VakapayRepositoryFactory.GetWalletRepository(DbConnection)) { var walletCheck = walletRepository.FindById(walletId); if (walletCheck == null) { return new ReturnObject { Status = Status.STATUS_ERROR, Message = "Wallet Not Found" } } ; VakacoinRpcObj = rpcClass as VakacoinRpc; var results = CreateNewAccount(walletId); // Create account and add account name to VakacoinAccount table if (results.Status == Status.STATUS_ERROR) { return(results); } return(new ReturnObject { Status = Status.STATUS_SUCCESS, Message = "Create vakacoin account success!" }); } } catch (Exception e) { return(new ReturnObject { Status = Status.STATUS_ERROR, Message = e.Message }); } }
/// <summary> /// Created Address with optimistic lock /// </summary> /// <param name="repoQuery"></param> /// <param name="rpcClass"></param> /// <param name="walletId"></param> /// <param name="other"></param> /// <typeparam name="TBlockchainAddress"></typeparam> /// <returns></returns> public virtual async Task <ReturnObject> CreateAddressAsync <TBlockchainAddress>( IAddressRepository <TBlockchainAddress> repoQuery, IBlockchainRpc rpcClass, string userId, string other = "") where TBlockchainAddress : BlockchainAddress { try { using (var userRepository = SmartContractRepositoryFactory.GetUserRepository(DbConnection)) { var walletCheck = userRepository.FindById(userId); if (walletCheck == null) { return new ReturnObject { Status = Status.STATUS_ERROR, Message = "Wallet Not Found" } } ; } var resultsRPC = rpcClass.CreateNewAddress(other); if (resultsRPC.Status == Status.STATUS_ERROR) { return(resultsRPC); } var address = resultsRPC.Data; var resultDB = await repoQuery.InsertAddress(address, userId, other); return(new ReturnObject { Status = resultDB.Status, Message = resultDB.Message }); } catch (Exception e) { return(new ReturnObject { Status = Status.STATUS_ERROR, Message = e.Message }); } }
/// <summary> /// Send Transaction with optimistic lock /// Send with multiple thread /// </summary> /// <param name="repoQuery"></param> /// <param name="rpcClass"></param> /// <param name="privateKey"></param> /// <typeparam name="TBlockchainTransaction"></typeparam> /// <returns></returns> public virtual async Task <ReturnObject> SendTransactionAsync <TBlockchainTransaction>( IRepositoryBlockchainTransaction <TBlockchainTransaction> repoQuery, IBlockchainRpc rpcClass, string privateKey = "") where TBlockchainTransaction : BlockchainTransaction { /* * 1. Query Transaction Withdraw pending * 2. Update Processing = 1, version = version + 1 * 3. Commit Transaction * 4. Call RPC send transaction * 5. Update Transaction Status */ // find transaction pending // var pendingTransaction = repoQuery.FindTransactionPending(); var pendingTransaction = repoQuery.FindRowPending(); if (pendingTransaction?.Id == null) { //if (!CacheHelper.HaveKey("cache")) //{ // long numberOfTicks = (DateTime.Now.Ticks - startTime); // TimeSpan ts = TimeSpan.FromTicks(numberOfTicks); // double minutesFromTs = ts.TotalMinutes; // CacheHelper.SetCacheString("cache", minutesFromTs.ToString()); //} //Console.WriteLine("END TIME " + CacheHelper.GetCacheString("cache")); return(new ReturnObject { Status = Status.STATUS_SUCCESS, Message = "Not found Transaction" }); } if (DbConnection.State != ConnectionState.Open) { //Console.WriteLine(DbConnection.State); DbConnection.Open(); } //begin first transaction var transactionScope = DbConnection.BeginTransaction(); try { //lock transaction for process var resultLock = await repoQuery.LockForProcess(pendingTransaction); if (resultLock.Status == Status.STATUS_ERROR) { transactionScope.Rollback(); return(new ReturnObject { Status = Status.STATUS_SUCCESS, Message = "Cannot Lock For Process" }); } //commit transaction transactionScope.Commit(); } catch (Exception e) { transactionScope.Rollback(); return(new ReturnObject { Status = Status.STATUS_ERROR, Message = e.ToString() }); } //Update Version to Model pendingTransaction.Version += 1; //start send and update var transactionDbSend = DbConnection.BeginTransaction(); try { //Call RPC Transaction //TODO EDIT RPC Class var sendTransaction = await rpcClass.SendTransactionAsync(pendingTransaction); pendingTransaction.Status = sendTransaction.Status; pendingTransaction.IsProcessing = 0; // pendingTransaction.UpdatedAt = (int) CommonHelper.GetUnixTimestamp(); // set in SafeUpdate pendingTransaction.Hash = sendTransaction.Data; //create database email when send success if (sendTransaction.Status == Status.STATUS_COMPLETED) { var email = GetEmailByTransaction(pendingTransaction); if (email != null) { // await CreateDataEmail("Notify send " + pendingTransaction.NetworkName(), // email, pendingTransaction.Amount, // Constants.TEMPLATE_EMAIL_SENT, pendingTransaction.NetworkName(),Constants.TYPE_SEND); await SendMailBusiness.SendMailBusiness.CreateDataEmail("Notify send " + pendingTransaction.NetworkName(), email, pendingTransaction.Amount, pendingTransaction.Id, EmailTemplate.Sent, pendingTransaction.NetworkName(), VakapayRepositoryFactory, false); } } var result = await repoQuery.SafeUpdate(pendingTransaction); if (result.Status == Status.STATUS_ERROR) { transactionDbSend.Rollback(); return(new ReturnObject { Status = Status.STATUS_ERROR, Message = "Cannot Save Transaction Status" }); } transactionDbSend.Commit(); return(new ReturnObject { Status = sendTransaction.Status, Message = sendTransaction.Message, Data = sendTransaction.Data }); } catch (Exception e) { //release lock transactionDbSend.Rollback(); var resultRelease = repoQuery.ReleaseLock(pendingTransaction); Console.WriteLine(JsonHelper.SerializeObject(resultRelease)); throw e; } }
public virtual async Task <ReturnObject> ScanBlockAsync <TWithDraw, TDeposit, TBlockResponse, TTransaction>( string networkName, IWalletBusiness wallet, IRepositoryBlockchainTransaction <TWithDraw> withdrawRepoQuery, IRepositoryBlockchainTransaction <TDeposit> depositRepoQuery, IBlockchainRpc rpcClass) where TWithDraw : BlockchainTransaction where TDeposit : BlockchainTransaction where TBlockResponse : EthereumBlockResponse where TTransaction : EthereumTransactionResponse { try { int lastBlock = -1; int blockNumber = -1; //Get lastBlock from last time int.TryParse( CacheHelper.GetCacheString(String.Format(RedisCacheKey.KEY_SCANBLOCK_LASTSCANBLOCK, networkName)), out lastBlock); if (lastBlock < 0) { lastBlock = 0; } //get blockNumber: var _result = rpcClass.GetBlockNumber(); if (_result.Status == Status.STATUS_ERROR) { throw new Exception("Cant GetBlockNumber"); } if (!int.TryParse(_result.Data.ToString(), out blockNumber)) { throw new Exception("Cant parse block number"); } //Get list of new block that have transactions if (lastBlock >= blockNumber) { lastBlock = blockNumber; } Console.WriteLine("SCAN FROM " + lastBlock + "___" + blockNumber); List <TBlockResponse> blocks = new List <TBlockResponse>(); for (int i = lastBlock; i <= blockNumber; i++) { if (i < 0) { continue; } _result = rpcClass.GetBlockByNumber(i); if (_result.Status == Status.STATUS_ERROR) { return(_result); } if (_result.Data == null) { continue; } TBlockResponse _block = JsonHelper.DeserializeObject <TBlockResponse>(_result.Data.ToString()); if (_block.TransactionsResponse.Length > 0) { blocks.Add(_block); } } CacheHelper.SetCacheString(String.Format(RedisCacheKey.KEY_SCANBLOCK_LASTSCANBLOCK, networkName), blockNumber.ToString()); if (blocks.Count <= 0) { throw new Exception("no blocks have transaction"); } //Get done,List<> blocks now contains all block that have transaction //check Transaction and update: //Search transactions which need to scan: var withdrawPendingTransactions = withdrawRepoQuery.FindTransactionsNotCompleteOnNet(); //Scan all block and check Withdraw transaction: Console.WriteLine("Scan withdrawPendingTransactions"); if (withdrawPendingTransactions.Count > 0) { foreach (TBlockResponse _block in blocks) { if (withdrawPendingTransactions.Count <= 0) { //SCAN DONE: break; } for (int i = withdrawPendingTransactions.Count - 1; i >= 0; i--) { BlockchainTransaction _currentPending = withdrawPendingTransactions[i]; EthereumTransactionResponse _trans = _block.TransactionsResponse.SingleOrDefault(x => x.Hash.Equals(_currentPending.Hash)); int _blockNumber = -1; int _fee = 0; if (_trans != null) { _trans.BlockNumber.HexToInt(out _blockNumber); if (_trans.Fee != null) { _trans.Fee.HexToInt(out _fee); } Console.WriteLine("HELLO " + _currentPending.Hash); _currentPending.BlockNumber = _blockNumber; _currentPending.Fee = _fee; _currentPending.UpdatedAt = (int)CommonHelper.GetUnixTimestamp(); // _currentPending.Status = Status.StatusCompleted; // _currentPending.InProcess = 0; Console.WriteLine("CaLL UPDATE"); portfolioHistoryBusiness.InsertWithPrice(_currentPending.UserId); withdrawRepoQuery.Update((TWithDraw)_currentPending); withdrawPendingTransactions.RemoveAt(i); } } } } Console.WriteLine("Scan withdrawPendingTransactions Done"); //check wallet balance and update foreach (TBlockResponse _block in blocks) { foreach (EthereumTransactionResponse _trans in _block.TransactionsResponse) { string _toAddress = _trans.To; string _fromAddress = _trans.From; if (!wallet.CheckExistedAddress(_toAddress, networkName)) { //logger.Info(to + " is not exist in Wallet!!!"); continue; } else { //Console.WriteLine("value" + _trans.value); int _transaValue = 0; if (_trans.Value.HexToInt(out _transaValue)) { var userID = ""; // portfolioHistoryBusiness.InsertWithPrice(_trans.i); wallet.UpdateBalanceDeposit(_toAddress, (Decimal)_transaValue, networkName); } } } } return(new ReturnObject { Status = Status.STATUS_COMPLETED, Message = "Scan done" }); } catch (Exception e) { return(new ReturnObject { Status = Status.STATUS_ERROR, Message = e.Message }); } }
/// <summary> /// Send Transaction with optimistic lock /// Send with multiple thread /// </summary> /// <param name="repoQuery"></param> /// <param name="rpcClass"></param> /// <param name="privateKey"></param> /// <typeparam name="TBlockchainTransaction"></typeparam> /// <returns></returns> public virtual async Task <ReturnObject> SendTransactionAsync <TBlockchainTransaction>( IRepositoryBlockchainTransaction <TBlockchainTransaction> repoQuery, IBlockchainRpc rpcClass, string privateKey = "") where TBlockchainTransaction : BlockchainTransaction { /* * 1. Query Transaction Withdraw pending * 2. Update Processing = 1, version = version + 1 * 3. Commit Transaction * 4. Call RPC send transaction * 5. Update Transaction Status */ var pendingTransaction = repoQuery.FindRowPending(); if (pendingTransaction?.Id == null) { //Console.WriteLine("END TIME " + CacheHelper.GetCacheString("cache")); return(new ReturnObject { Status = Status.STATUS_SUCCESS, Message = "Not found Transaction" }); } if (DbConnection.State != ConnectionState.Open) { //Console.WriteLine(DbConnection.State); DbConnection.Open(); } //begin first transaction var transactionScope = DbConnection.BeginTransaction(); try { //lock transaction for process var resultLock = await repoQuery.LockForProcess(pendingTransaction); if (resultLock.Status == Status.STATUS_ERROR) { transactionScope.Rollback(); return(new ReturnObject { Status = Status.STATUS_SUCCESS, Message = "Cannot Lock For Process" }); } //commit transaction transactionScope.Commit(); } catch (Exception e) { transactionScope.Rollback(); return(new ReturnObject { Status = Status.STATUS_ERROR, Message = e.ToString() }); } //Update Version to Model pendingTransaction.Version += 1; //start send and update var transactionDbSend = DbConnection.BeginTransaction(); try { //Call RPC Transaction //TODO EDIT RPC Class var sendTransaction = await rpcClass.SendTransactionAsync1(pendingTransaction); pendingTransaction.Status = sendTransaction.Status; pendingTransaction.IsProcessing = 0; pendingTransaction.Hash = sendTransaction.Data; //create database email when send success if (sendTransaction.Status == Status.STATUS_COMPLETED) { // var email = GetEmailByTransaction(pendingTransaction); // if (email != null) // { // // await SendMailBusiness.SendMailBusiness.CreateDataEmail( // "Notify send " + pendingTransaction.NetworkName(), // email, pendingTransaction.Amount, pendingTransaction.Id, // EmailTemplate.Sent, pendingTransaction.NetworkName(), SmartContractRepositoryFactory, // false); // } } var result = await repoQuery.SafeUpdate(pendingTransaction); if (result.Status == Status.STATUS_ERROR) { transactionDbSend.Rollback(); return(new ReturnObject { Status = Status.STATUS_ERROR, Message = "Cannot Save Transaction Status" }); } transactionDbSend.Commit(); return(new ReturnObject { Status = sendTransaction.Status, Message = sendTransaction.Message, Data = sendTransaction.Data }); } catch (Exception e) { //release lock Console.WriteLine(e.Message); transactionDbSend.Rollback(); var resultRelease = repoQuery.ReleaseLock(pendingTransaction); Console.WriteLine(JsonHelper.SerializeObject(resultRelease)); throw e; } }