public IRpcMethodResult GetTxOutSetInfo() { try { GetTxOutSetInfoOM result = new GetTxOutSetInfoOM(); var blockComponent = new BlockComponent(); var txComponent = new TransactionComponent(); var utxoComponent = new UtxoComponent(); result.height = blockComponent.GetLatestHeight(); result.bestblock = null; if (result.height >= 0) { var bestBlock = blockComponent.GetBlockMsgByHeight(result.height); result.bestblock = bestBlock != null ? bestBlock.Header.Hash : null; } result.transactions = utxoComponent.GetTransactionCounts(); result.txouts = utxoComponent.GetOutputCounts(); long confirmedBalance, unconfirmedBalance; utxoComponent.GetBalanceInDB(out confirmedBalance, out unconfirmedBalance); result.total_amount = confirmedBalance; return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
public P2PJob() { this.p2pComponent = new P2PComponent(); this.txComponent = new TransactionComponent(); this.blockComponent = new BlockComponent(); blockSyncTimer = new System.Timers.Timer(10 * 1000); blockSyncTimer.AutoReset = true; blockSyncTimer.Elapsed += blockSyncTimer_Elapsed; }
public IRpcMethodResult GetTxOut(string txid, int vount, bool unconfirmed = false) { try { GetTxOutOM result = null; var txComponent = new TransactionComponent(); var blockComponent = new BlockComponent(); string blockHash = null; TransactionMsg tx = txComponent.GetTransactionMsgFromDB(txid, out blockHash); if (tx == null && unconfirmed) { tx = txComponent.GetTransactionMsgFromPool(txid); } if (tx != null && tx.OutputCount > vount) { var output = tx.Outputs[vount]; long confirmations = 0; if (!string.IsNullOrWhiteSpace(blockHash)) { var block = blockComponent.GetBlockMsgByHash(blockHash); if (block != null) { var latestHeight = blockComponent.GetLatestHeight(); if (latestHeight > block.Header.Height) { confirmations = latestHeight - block.Header.Height; } } } result = new GetTxOutOM(); result.bestblock = blockHash; result.confirmations = confirmations; result.value = output.Amount; result.scriptPubKey = output.LockScript; result.version = tx.Version; result.coinbase = (tx.InputCount == 0 && tx.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash())); } return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
public P2PJob() { this.p2pComponent = new P2PComponent(); this.txComponent = new TransactionComponent(); this.blockComponent = new BlockComponent(); MiningPoolComponent.OnNewMiningPoolHandle = (msg) => receivedNewMiningPoolMessage(null, msg); blockSyncTimer = new System.Timers.Timer(10 * 1000); blockSyncTimer.AutoReset = true; blockSyncTimer.Elapsed += blockSyncTimer_Elapsed; }
private static Transaction AddProducts(Transaction transaction, Staff staff) { bool addingFinished = false; List <Product> products = ProductHandler.GetAllProducts(); Console.WriteLine("** Add products to transaction **\n"); while (!addingFinished) { Console.Clear(); PrintSummary(transaction); Console.WriteLine("\n"); ProductHandler.PrintInfoList(products); Console.WriteLine("Enter the id of the product wanted - enter 0 if you are finished.\n"); Console.Write("Id: "); string idInput = Console.ReadLine(); if (idInput == "0") { break; } try { int productId = int.Parse(idInput); Product wantedProduct = products.Find(p => p.Id == productId); if (wantedProduct != null) { Console.WriteLine("Enter the quantity required. Use , if decimals required"); Console.Write("Quantity: "); double quantity = double.Parse(Console.ReadLine()); TransactionComponent productToAdd = TransactionComponentHandler.Create(transaction, wantedProduct, quantity); transaction.TransactionComponent.Add(productToAdd); Console.WriteLine(String.Format("{0} * {1} à {2} was added to transaction", quantity, productToAdd.ProductName, productToAdd.ProductPrice)); } else { Console.WriteLine(String.Format("No product with id {0} was found", productId)); } } catch (FormatException) { Console.WriteLine("Invalid format of input"); } } return(transaction); }
public IRpcMethodResult GeTransaction(string txId) { try { var result = new TransactionComponent().GetTransactionEntityByHash(txId); return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
public IRpcMethodResult GetAllTxInMemPool() { try { var result = new TransactionComponent().GetAllHashesRelevantWithCurrentWalletFromPool(); return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
/// <summary> /// CoinEgg专用,获取数据库中为未费的所有总额 /// </summary> /// <returns></returns> public IRpcMethodResult GetTotalBalance() { try { var transactionComponent = new TransactionComponent(); var result = transactionComponent.GetTotalBalance(); return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
public IRpcMethodResult GetTxOut(string txid, int vount, bool unconfirmed = false) { try { var transactionComponent = new TransactionComponent(); var result = transactionComponent.GetTxOut(txid, vount); return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
public IRpcMethodResult GetTransactionInfo(string transactionHash) { try { TransactionComponent component = new TransactionComponent(); var result = component.GetTransactionDetail(transactionHash); return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
/// <summary> /// 判断交易是否合法 /// </summary> /// <param name="dic"></param> /// <returns></returns> public IRpcMethodResult IsTransactionValid(Dictionary <string, int> dic) { try { TransactionComponent trans = new TransactionComponent(); bool result = trans.IsTransactionValid(dic); return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
internal static TransactionComponent Create(Transaction transaction, Product product, double quantity) { TransactionComponent output = new TransactionComponent { /* * We dont want to save the actual Product in the transaction because if we later on change the price * of something that previously has been bought all the historical transactions will be modified so we "clone" the product into a component of a transaction * */ Transaction = transaction, ProductName = product.Name, ProductPrice = product.Price, ProductCategory = product.Category, Quantity = quantity, }; return(output); }
/// <summary> /// 根据txhash判断交易是否打包 /// </summary> /// <param name="txHash"></param> /// <returns></returns> public IRpcMethodResult IsTxHashExists(string txHash) { try { TransactionComponent trans = new TransactionComponent(); bool result = trans.CheckTxExisted(txHash, false); return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
/// <summary> /// 锁定未花费的输出 /// </summary> /// <param name="isLocked">true为已锁定,false为未锁定</param> /// <param name="transaction">需要锁定的交易</param> /// <returns></returns> public IRpcMethodResult LockUnspent(bool isLocked, ListLockUnspentOM[] transaction) { try { /* 1、把输入的参数用个静态变量存储起来 * 2、当转账或其他交易的时候先判断是否在静态变量中存在,如果存在就跳过, * 3、注意修改对应的转账接口 */ //根据Transaction的txid和vout获取outputList的ReceivedId TransactionComponent component = new TransactionComponent(); AccountComponent account = new AccountComponent(); List <string> accountIdList = AccountDac.Default.GetAccountBook(); foreach (var item in transaction) { string receivedId = component.GetUtxoSetByIndexAndTxHash(item.txid, item.vout)?.Account; //只锁定自己的账户 if (accountIdList.Contains(receivedId)) { if (isLocked) { Startup.lockUnspentList.Add(item); } else { Startup.lockUnspentList.Remove(Startup.lockUnspentList.FirstOrDefault(p => p.txid == item.txid && p.vout == item.vout)); } } } //去除重复数据 Startup.lockUnspentList = Startup.lockUnspentList.GroupBy(p => new { p.txid, p.vout }).Select(q => q.First()).ToList(); return(Ok(isLocked)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
private void transactionTest() { var utxoComponent = new UtxoComponent(); var transactionComponent = new TransactionComponent(); var accountComponent = new AccountComponent(); if (string.IsNullOrWhiteSpace(this.newAccountId)) { var newAccount = accountComponent.GenerateNewAccount(); this.newAccountId = newAccount.Id; } var defaultAccount = accountComponent.GetDefaultAccount(); if (defaultAccount != null) { var balance = utxoComponent.GetConfirmedBlanace(defaultAccount.Id); var amount = 50000000000L; var fee = 1000000L; if (balance > (amount + fee)) { var dict = new Dictionary <string, long>(); dict.Add(newAccountId, amount); var txMsg = transactionComponent.CreateNewTransactionMsg(defaultAccount.Id, dict, fee); transactionComponent.AddTransactionToPool(txMsg); LogHelper.Debug("====== A New transaction has been created. " + txMsg.Hash); if (BlockchainJob.Current.P2PJob != null) { BlockchainJob.Current.P2PJob.BroadcastNewTransactionMessage(txMsg.Hash); } } } }
private TransactionComponent[] GetTransactionComponentsByClaimNumber(string claimNumber) { var transactionComponentTable = importedData.FirstOrDefault(o => o.TableName.Equals(Constants.ClaimTransactionComponent)); var transactionComponents = new List <TransactionComponent>(); if (transactionComponentTable != null) { foreach (DataRow row in transactionComponentTable.Rows) { try { if (claimNumber.Equals(row["KeyInternSchadenummer"])) { var transactionComponent = new TransactionComponent { KeyIdPolis = row["KeyIdPolis"].ToString(), KeyDekkingsNummer = row["KeyDekkingsNummer"].ToString(), KeySchadeBoekingsNummer = row["KeySchadeBoekingsNummer"].ToString(), TransactionAmount = row["TransactionAmount"].ToString(), TransactionComponentTypeCode = row["TransactionComponentTypeCode"].ToString(), TransactionComponentTypeDescription = row["TransactionComponentTypeDescription"].ToString() }; transactionComponents.Add(transactionComponent); } } catch (Exception ex) { Logger.Log(LogLevel.Error, ex, $"While importing EDF claim transaction component for - {row["KeyInternSchadenummer"]} : ClaimNumber and PolicyId : {row["KeyIdPolis"]}"); } } } return(transactionComponents.ToArray()); }
internal static string Summarize(TransactionComponent tc) { return(String.Format("{0} - {1} * {2} - {3}", tc.ProductName, tc.ProductPrice, tc.Quantity, tc.ProductPrice * tc.Quantity)); }
public IRpcMethodResult ListTransactions(string account, int count, int skip = 0, bool includeWatchOnly = true) { try { var txComponent = new TransactionComponent(); var accountComponent = new AccountComponent(); var addressBookComponent = new AddressBookComponent(); var utxoComponent = new UtxoComponent(); var blockComponent = new BlockComponent(); var transactionCommentComponent = new TransactionCommentComponent(); List <PaymentOM> result = new List <PaymentOM>(); var accounts = accountComponent.GetAllAccounts(); var paymentAccountIds = accounts.Where(a => !string.IsNullOrWhiteSpace(a.PrivateKey)).Select(a => a.Id).ToList(); var allAccountIds = accounts.Select(a => a.Id).ToList(); var addressBook = addressBookComponent.GetWholeAddressBook(); var latestHeight = blockComponent.GetLatestHeight(); var data = txComponent.SearchTransactionEntities(account, count, skip, includeWatchOnly); foreach (var tx in data) { long totalInput = 0; long selfTotalOutput = 0; long otherUserTotalOutput = 0; bool coibase = false; if (tx.Inputs.Count == 1 && tx.Outputs.Count == 1 && tx.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash())) { coibase = true; } if (!coibase) { foreach (var input in tx.Inputs) { var oldOutput = txComponent.GetOutputEntiyByIndexAndTxHash(input.OutputTransactionHash, input.OutputIndex); if (oldOutput != null && paymentAccountIds.Contains(oldOutput.ReceiverId)) { totalInput += input.Amount; } else { totalInput = 0; break; } } } foreach (var output in tx.Outputs) { if (allAccountIds.Contains(output.ReceiverId)) { selfTotalOutput += output.Amount; } else { otherUserTotalOutput += output.Amount; } } BlockMsg block = null; if (tx.BlockHash != null) { block = blockComponent.GetBlockMsgByHash(tx.BlockHash); } if (coibase) { var payment = new PaymentOM(); payment.address = tx.Outputs[0].ReceiverId; payment.account = accounts.Where(a => a.Id == payment.address).Select(a => a.Tag).FirstOrDefault(); payment.category = "generate"; payment.totalInput = totalInput; payment.totalOutput = selfTotalOutput; payment.amount = selfTotalOutput; payment.fee = 0; payment.txId = tx.Hash; payment.vout = 0; payment.time = tx.Timestamp; payment.size = tx.Size; var txComment = transactionCommentComponent.GetByTransactionHashAndIndex(tx.Hash, 0); if (txComment != null) { payment.comment = txComment.Comment; } if (block != null) { payment.blockHash = tx.BlockHash; payment.blockIndex = 0;// block.Transactions.FindIndex(t=>t.Hash == tx.Hash); payment.blockTime = block.Header.Timestamp; payment.confirmations = latestHeight - block.Header.Height + 1; } else { payment.confirmations = 0; } result.Add(payment); } else if (totalInput > 0 && otherUserTotalOutput == 0) { var payment = new PaymentOM(); payment.address = null; payment.account = null; payment.category = "self"; payment.totalInput = totalInput; payment.totalOutput = tx.Outputs[0].Amount;// selfTotalOutput; payment.fee = totalInput - selfTotalOutput; payment.amount = payment.fee; payment.txId = tx.Hash; payment.vout = 0; payment.time = tx.Timestamp; payment.size = tx.Size; var txComments = transactionCommentComponent.GetByTransactionHash(tx.Hash); if (txComments.Count > 0) { payment.comment = ""; foreach (var item in txComments) { if (!string.IsNullOrWhiteSpace(item.Comment)) { payment.comment += item.Comment + ";"; } } } if (block != null) { payment.blockHash = tx.BlockHash; payment.blockIndex = block.Transactions.FindIndex(t => t.Hash == tx.Hash); payment.blockTime = block.Header.Timestamp; payment.confirmations = latestHeight - block.Header.Height + 1; } else { payment.confirmations = 0; } result.Add(payment); } else if (totalInput > 0) { for (int i = 0; i < tx.Outputs.Count; i++) { if (!allAccountIds.Contains(tx.Outputs[i].ReceiverId)) { var payment = new PaymentOM(); payment.address = tx.Outputs[i].ReceiverId; payment.account = addressBook.Where(a => a.Address == payment.address && !string.IsNullOrWhiteSpace(a.Tag)).Select(a => a.Tag).FirstOrDefault(); payment.category = "send"; payment.totalInput = totalInput; payment.totalOutput = tx.Outputs[i].Amount; payment.fee = totalInput - (selfTotalOutput + otherUserTotalOutput); payment.amount = (i == 0 ? tx.Outputs[i].Amount + payment.fee : tx.Outputs[i].Amount); payment.txId = tx.Hash; payment.vout = i; payment.time = tx.Timestamp; payment.size = tx.Size; var txComment = transactionCommentComponent.GetByTransactionHashAndIndex(tx.Hash, i); if (txComment != null) { payment.comment = txComment.Comment; } if (block != null) { payment.blockHash = tx.BlockHash; payment.blockIndex = block.Transactions.FindIndex(t => t.Hash == tx.Hash); payment.blockTime = block.Header.Timestamp; payment.confirmations = latestHeight - block.Header.Height + 1; } else { payment.confirmations = 0; } result.Add(payment); } } } else { for (int i = 0; i < tx.Outputs.Count; i++) { if (allAccountIds.Contains(tx.Outputs[i].ReceiverId)) { var payment = new PaymentOM(); payment.address = tx.Outputs[i].ReceiverId; payment.account = accounts.Where(a => a.Id == payment.address).Select(a => a.Tag).FirstOrDefault();; payment.category = "receive"; payment.totalInput = totalInput; payment.totalOutput = tx.Outputs[i].Amount; payment.fee = totalInput - (selfTotalOutput + otherUserTotalOutput); payment.amount = tx.Outputs[i].Amount; payment.txId = tx.Hash; payment.vout = i; payment.time = tx.Timestamp; payment.size = tx.Size; var txComment = transactionCommentComponent.GetByTransactionHashAndIndex(tx.Hash, i); if (txComment != null) { payment.comment = txComment.Comment; } if (block != null) { payment.blockHash = tx.BlockHash; payment.blockIndex = block.Transactions.FindIndex(t => t.Hash == tx.Hash); payment.blockTime = block.Header.Timestamp; payment.confirmations = latestHeight - block.Header.Height + 1; } else { payment.confirmations = 0; } result.Add(payment); } } } } return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
public MinerJob(string minerName) { blockComponent = new BlockComponent(); txComponent = new TransactionComponent(); this.minerName = minerName; }
public IRpcMethodResult EstimateTxFeeForSendToAddress(string toAddress, long amount, string comment, string commentTo, bool deductFeeFromAmount) { try { EstimateTxFeeOM result = new EstimateTxFeeOM(); var utxoComponent = new UtxoComponent(); var txComponent = new TransactionComponent(); var settingComponent = new SettingComponent(); var addressBookComponent = new AddressBookComponent(); var accountComponent = new AccountComponent(); if (!AccountIdHelper.AddressVerify(toAddress)) { throw new CommonException(ErrorCode.Service.Transaction.TO_ADDRESS_INVALID); } var setting = settingComponent.GetSetting(); var utxos = utxoComponent.GetAllConfirmedOutputs(); var tx = new TransactionMsg(); var totalSize = tx.Serialize().Length; var output = new OutputMsg(); output.Amount = amount; output.Index = 0; output.LockScript = Script.BuildLockScipt(toAddress); output.Size = output.LockScript.Length; tx.Outputs.Add(output); totalSize += output.Serialize().Length; var blockComponent = new BlockComponent(); var lastBlockHeight = blockComponent.GetLatestHeight(); var totalInput = 0L; var index = 0; double totalAmount = amount; double totalFee = setting.FeePerKB * ((double)totalSize / 1024.0); while (index < utxos.Count) { var account = accountComponent.GetAccountById(utxos[index].AccountId); if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey)) { var utxoTX = txComponent.GetTransactionMsgByHash(utxos[index].TransactionHash); Block utxoBlock = blockComponent.GetBlockEntiytByHash(utxos[index].BlockHash); if (utxoTX == null || utxoBlock == null) { index++; continue; } if (!utxoBlock.IsVerified) { index++; continue; } if (Time.EpochTime < utxoTX.Locktime) { index++; continue; } if (utxoTX.InputCount == 1 && utxoTX.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash())) { var blockHeight = utxoBlock.Height; if (lastBlockHeight - blockHeight < 100L) { index++; continue; } } var input = new InputMsg(); input.OutputTransactionHash = utxos[index].TransactionHash; input.OutputIndex = utxos[index].OutputIndex; input.UnlockScript = Script.BuildUnlockScript(input.OutputTransactionHash, input.OutputIndex, Base16.Decode(decryptPrivateKey(account.PrivateKey)), Base16.Decode(account.PublicKey)); input.Size = input.UnlockScript.Length; tx.Inputs.Add(input); var size = input.Serialize().Length; totalSize += size; totalFee += setting.FeePerKB * ((double)size / 1024.0); totalInput += utxos[index].Amount; } else { index++; continue; } if (!deductFeeFromAmount) { totalAmount = amount + totalFee; } if (totalInput >= (long)Math.Ceiling(totalAmount)) { var size = output.Serialize().Length; if ((totalInput - (long)Math.Ceiling(totalAmount)) > (setting.FeePerKB * (double)size / 1024.0)) { totalSize += size; totalFee += setting.FeePerKB * ((double)size / 1024.0); } break; } index++; } if (totalInput < totalAmount) { throw new CommonException(ErrorCode.Service.Transaction.BALANCE_NOT_ENOUGH); } if (deductFeeFromAmount) { output.Amount -= (long)Math.Ceiling(totalFee); if (output.Amount <= 0) { throw new CommonException(ErrorCode.Service.Transaction.SEND_AMOUNT_LESS_THAN_FEE); } } result.totalFee = Convert.ToInt64(totalFee); result.totalSize = Convert.ToInt32(totalSize); return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
public IRpcMethodResult SendMany(string fromAccount, SendManyOutputIM[] receivers, string[] feeDeductAddresses) { try { string result = null; var utxoComponent = new UtxoComponent(); var txComponent = new TransactionComponent(); var settingComponent = new SettingComponent(); var addressBookComponent = new AddressBookComponent(); var accountComponent = new AccountComponent(); var transactionCommentComponent = new TransactionCommentComponent(); var blockComponent = new BlockComponent(); var lastBlockHeight = blockComponent.GetLatestHeight(); var setting = settingComponent.GetSetting(); var utxos = utxoComponent.GetAllConfirmedOutputs(); var tx = new TransactionMsg(); double totalOutput = 0; var totalSize = tx.Serialize().Length; if (receivers == null || receivers.Length == 0) { throw new CommonException(ErrorCode.Service.Transaction.TO_ADDRESS_INVALID); } foreach (var receiver in receivers) { if (!AccountIdHelper.AddressVerify(receiver.address)) { throw new CommonException(ErrorCode.Service.Transaction.TO_ADDRESS_INVALID); } var output = new OutputMsg(); output.Amount = receiver.amount; output.Index = tx.Outputs.Count; output.LockScript = Script.BuildLockScipt(receiver.address); output.Size = output.LockScript.Length; tx.Outputs.Add(output); totalSize += output.Serialize().Length; totalOutput += receiver.amount; } foreach (var address in feeDeductAddresses) { if (receivers.Where(r => r.address == address).Count() == 0) { throw new CommonException(ErrorCode.Service.Transaction.FEE_DEDUCT_ADDRESS_INVALID); } } var totalInput = 0L; var index = 0; double totalFee = setting.FeePerKB * ((double)totalSize / 1024.0); double totalAmount = totalOutput; while (index < utxos.Count) { var account = accountComponent.GetAccountById(utxos[index].AccountId); if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey)) { var utxoTX = txComponent.GetTransactionMsgByHash(utxos[index].TransactionHash); Block utxoBlock = blockComponent.GetBlockEntiytByHash(utxos[index].BlockHash); if (utxoTX == null || utxoBlock == null) { index++; continue; } if (!utxoBlock.IsVerified) { index++; continue; } if (Time.EpochTime < utxoTX.Locktime) { index++; continue; } if (utxoTX.InputCount == 1 && utxoTX.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash())) { var blockHeight = utxoBlock.Height; if (lastBlockHeight - blockHeight < 100L) { index++; continue; } } var input = new InputMsg(); input.OutputTransactionHash = utxos[index].TransactionHash; input.OutputIndex = utxos[index].OutputIndex; input.UnlockScript = Script.BuildUnlockScript(input.OutputTransactionHash, input.OutputIndex, Base16.Decode(decryptPrivateKey(account.PrivateKey)), Base16.Decode(account.PublicKey)); input.Size = input.UnlockScript.Length; tx.Inputs.Add(input); var size = input.Serialize().Length; totalSize += size; totalFee += setting.FeePerKB * ((double)size / 1024.0); totalInput += utxos[index].Amount; } else { index++; continue; } if (feeDeductAddresses == null || feeDeductAddresses.Length == 0) { totalAmount = totalOutput + totalFee; } if (totalInput >= (long)Math.Ceiling(totalAmount)) { var size = tx.Outputs[0].Serialize().Length; if ((totalInput - (long)Math.Ceiling(totalAmount)) > (setting.FeePerKB * (double)size / 1024.0)) { totalSize += size; totalFee += setting.FeePerKB * ((double)size / 1024.0); if (feeDeductAddresses == null || feeDeductAddresses.Length == 0) { totalAmount = totalOutput + totalFee; } var newAccount = accountComponent.GenerateNewAccount(); if (setting.Encrypt) { if (!string.IsNullOrWhiteSpace(_cache.Get <string>("WalletPassphrase"))) { newAccount.PrivateKey = AES128.Encrypt(newAccount.PrivateKey, _cache.Get <string>("WalletPassphrase")); accountComponent.UpdatePrivateKeyAr(newAccount); } else { throw new CommonException(ErrorCode.Service.Wallet.WALLET_HAS_BEEN_LOCKED); } } var newOutput = new OutputMsg(); newOutput.Amount = totalInput - (long)Math.Ceiling(totalAmount); newOutput.Index = tx.Outputs.Count; newOutput.LockScript = Script.BuildLockScipt(newAccount.Id); newOutput.Size = newOutput.LockScript.Length; tx.Outputs.Add(newOutput); } break; } index++; } if (totalInput < totalAmount) { throw new CommonException(ErrorCode.Service.Transaction.BALANCE_NOT_ENOUGH); } if (feeDeductAddresses != null && feeDeductAddresses.Length > 0) { var averageFee = totalFee / feeDeductAddresses.Length; for (int i = 0; i < receivers.Length; i++) { if (feeDeductAddresses.Contains(receivers[i].address)) { tx.Outputs[i].Amount -= (long)Math.Ceiling(averageFee); if (tx.Outputs[i].Amount <= 0) { throw new CommonException(ErrorCode.Service.Transaction.SEND_AMOUNT_LESS_THAN_FEE); } } } } tx.Timestamp = Time.EpochTime; tx.Hash = tx.GetHash(); txComponent.AddTransactionToPool(tx); Startup.P2PBroadcastTransactionAction(tx.Hash); result = tx.Hash; for (int i = 0; i < receivers.Length; i++) { var receiver = receivers[i]; if (!string.IsNullOrWhiteSpace(receiver.tag)) { addressBookComponent.SetTag(receiver.address, receiver.tag); } if (!string.IsNullOrWhiteSpace(receiver.comment)) { transactionCommentComponent.Add(tx.Hash, i, receiver.comment); } } return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
public IRpcMethodResult ListUnspent(int minConfirmations, int maxConfirmations = 9999999, string[] addresses = null) { try { var result = new List <ListUnspentOM>(); var txComponent = new TransactionComponent(); var blockComponent = new BlockComponent(); var outputComponent = new UtxoComponent(); var accountComponent = new AccountComponent(); var addressBookComponent = new AddressBookComponent(); var accounts = accountComponent.GetAllAccounts(); var transactions = txComponent.GetTransactionEntitiesContainUnspentUTXO(); var latestHeight = blockComponent.GetLatestHeight(); foreach (var tx in transactions) { var blockMsg = blockComponent.GetBlockMsgByHash(tx.BlockHash); if (blockMsg != null) { var confirmations = latestHeight - blockMsg.Header.Height; if (confirmations >= minConfirmations && confirmations <= maxConfirmations) { var outputs = txComponent.GetOutputEntitesByTxHash(tx.Hash); foreach (var output in outputs) { var pubKeyHash = Script.GetPublicKeyHashFromLockScript(output.LockScript); var address = AccountIdHelper.CreateAccountAddressByPublicKeyHash(Base16.Decode(pubKeyHash)); var account = accounts.Where(a => a.Id == address).FirstOrDefault(); if (account != null) { if (addresses == null || addresses.Contains(address)) { result.Add(new ListUnspentOM { txid = output.TransactionHash, vout = output.Index, address = address, account = addressBookComponent.GetTagByAddress(address), scriptPubKey = output.LockScript, redeemScript = null, amount = output.Amount, confirmations = confirmations, spendable = string.IsNullOrWhiteSpace(account.PrivateKey), solvable = false }); } } } } } } return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }