public void PayOutCancel(SpendTx spend) { if (spend.ChangeAddress.Length > 0) { NodeCash.DeleteChangeKey(spend.ChangeAddress); } }
public bool PayAccountBalanceNode(SpendTx spendTx, string accountCode, string cashCodeForChange) { try { foreach (var tx in spendTx.Transactions) { Money minerFee = tx.MinerFee; for (int i = 0; i < tx.TxIds.Count; i++) { TxId input = tx.TxIds[i]; Money moneyOut = input.MoneyOut; if (i == tx.TxIds.Count - 1) { moneyOut -= tx.ChangeAmount; } NodeCash.proc_TxPayAccount ( tx.PaymentAddress, $"{input.TransactionId}", moneyOut.ToUnit(MoneyUnit.MilliBTC), minerFee.ToUnit(MoneyUnit.MilliBTC), accountCode ); minerFee = minerFee <= moneyOut ? Money.Zero : minerFee - moneyOut; } foreach (var output in tx.Tx.Outputs) { string toAddress = $"{output.ScriptPubKey.GetDestinationAddress(GetNetwork)}"; if (toAddress == spendTx.ChangeAddress) { string toTxId = $"{tx.Tx.GetHash()}"; NodeCash.proc_ChangeTxAdd ( toAddress, toTxId, (short)TxStatus.UTXO, output.Value.ToUnit(MoneyUnit.MilliBTC), 0, spendTx.TxMessage ); NodeCash.proc_TxPayInChange(CashAccountCode, toAddress, toTxId, accountCode, cashCodeForChange, Properties.Resources.PaymentChange); } } } return(true); } catch (Exception err) { Console.WriteLine($"Error: {err.Message}"); return(false); } }
public void KeyTransferCancel(SpendTx spend) { NodeCash.DeleteChangeKey(spend.ToAddress); if (spend.ChangeAddress.Length > 0) { NodeCash.DeleteChangeKey(spend.ChangeAddress); } }
public async Task <SpendTx> PayOutTx(AccountKey fromKey, string toAddress, decimal payAmount, int minersRate, string txMessage) { try { int?addressIndex = 0; string changeAddress = string.Empty; double accountBalance = await KeyNameBalance(fromKey.KeyName); if ((decimal)accountBalance > payAmount) { changeAddress = NewChangeKey(fromKey.KeyName, fromKey.HDPath, CoinChangeType.Change, ref addressIndex); if (!AddChangeKey(fromKey.KeyName, changeAddress, (int)addressIndex, null)) { return(null); } } string changePath = $"{fromKey.HDPath}{(short)CoinChangeType.Change}/{addressIndex}/"; Money spendAmount = new Money(payAmount, MoneyUnit.MilliBTC); SpendTx spend = new SpendTx(BlockchainApi) { ToAddress = toAddress, ChangeAddress = changeAddress, FromKey = fromKey.KeyName, ChangeKey = fromKey.KeyName, MinerRate = minersRate, TxMessage = txMessage, TargetAmount = spendAmount, AccountBalance = new Money((decimal)accountBalance, MoneyUnit.MilliBTC) }; var keyAddresses = NodeCash.fnKeyAddresses(CashAccountCode, fromKey.KeyName) .OrderBy(tb => tb.AddressIndex) .Select(tb => tb); foreach (var key in keyAddresses) { spend.AddKey(GetExtendedKey(key.HDPath), GetExtendedKey(changePath)); if (spend.IsSatisfied) { break; } } return(spend); } catch (Exception err) { Console.WriteLine($"Error: {err.Message}"); return(null); } }
private async void MiscellaneousPayment() { try { PayOutWindow payOut = new PayOutWindow(tcBitcoin, SelectedKey); if (payOut.ShowDialog() == true) { Cursor = Cursors.Wait; SpendTx spendTx = await tcBitcoin.PayOutTx(SelectedKey, payOut.PaymentAddress, payOut.AmountToPay, payOut.MinerRate, payOut.TxMessage); if (!spendTx.IsSatisfied) { MessageBox.Show(Properties.Resources.UnsatisfiedPayment, payOut.Title, MessageBoxButton.OK, MessageBoxImage.Error); tcBitcoin.PayOutCancel(spendTx); } else { Cursor = Cursors.Arrow; SpendConfirmWindow spendDialog = new SpendConfirmWindow(spendTx); if (spendDialog.ShowDialog() == true) { Cursor = Cursors.Wait; bool broadcast = await spendTx.Send(); if (broadcast) { if (tcBitcoin.PayOutMiscNode(spendTx, payOut.AccountCode, payOut.CashCode, payOut.TaxCode, payOut.PaymentReference)) { Refresh(); await RefreshBalance(); } } else { tcBitcoin.PayOutCancel(spendTx); } } else { tcBitcoin.PayOutCancel(spendTx); } } } } catch (Exception err) { MessageBox.Show($"{err.Message}", $"{err.Source}.{err.TargetSite.Name}", MessageBoxButton.OK, MessageBoxImage.Error); } finally { Cursor = Cursors.Arrow; } }
private async void PayAccount() { try { var invoice = (vwInvoicedPayments)dgInvoices.SelectedItem; AccountKey accountKey = (AccountKey)tvWallet.SelectedItem; PayAccountWindow payAccount = new PayAccountWindow(tcBitcoin, accountKey, invoice); if (payAccount.ShowDialog() == true) { Cursor = Cursors.Wait; SpendTx spendTx = await tcBitcoin.PayOutTx(accountKey, payAccount.PaymentAddress, payAccount.AmountToPay, payAccount.MinerRate, payAccount.TxMessage); if (!spendTx.IsSatisfied) { MessageBox.Show(Properties.Resources.UnsatisfiedPayment, payAccount.Title, MessageBoxButton.OK, MessageBoxImage.Error); tcBitcoin.PayOutCancel(spendTx); } else { Cursor = Cursors.Arrow; SpendConfirmWindow spendDialog = new SpendConfirmWindow(spendTx); if (spendDialog.ShowDialog() == true) { Cursor = Cursors.Wait; bool broadcast = await spendTx.Send(); if (broadcast) { if (tcBitcoin.PayAccountBalanceNode(spendTx, invoice.AccountCode, payAccount.CashCodeForChange)) { Refresh(); OnBalance?.Invoke(this, new EventArgs()); } } } else { tcBitcoin.PayOutCancel(spendTx); } } } } catch (Exception err) { MessageBox.Show($"{err.Message}", $"{err.Source}.{err.TargetSite.Name}", MessageBoxButton.OK, MessageBoxImage.Error); } finally { Cursor = Cursors.Arrow; } }
private async void KeyTransfer() { try { KeyTransferWindow keyTransfer = new KeyTransferWindow(tcBitcoin, SelectedKey); if (keyTransfer.ShowDialog() == true) { Cursor = Cursors.Wait; SpendTx spendTx = await tcBitcoin.KeyTransferTx(SelectedKey, GetKey(keyTransfer.KeyNameTo), keyTransfer.TransferAmount, keyTransfer.MinerRate, keyTransfer.TxMessage, keyTransfer.CashCodeFrom, keyTransfer.CashCodeTo); if (!spendTx.IsSatisfied) { MessageBox.Show(Properties.Resources.UnsatisfiedPayment, Title, MessageBoxButton.OK, MessageBoxImage.Error); tcBitcoin.KeyTransferCancel(spendTx); } else { Cursor = Cursors.Arrow; SpendConfirmWindow spendDialog = new SpendConfirmWindow(spendTx); if (spendDialog.ShowDialog() == true) { Cursor = Cursors.Wait; bool broadcast = await spendTx.Send(); if (broadcast) { if (tcBitcoin.KeyTransferNode(spendTx, keyTransfer.KeyNameTo, keyTransfer.CashCodeFrom, keyTransfer.CashCodeTo)) { Refresh(); await RefreshBalance(); } } } else { tcBitcoin.KeyTransferCancel(spendTx); } } } } catch (Exception err) { MessageBox.Show($"{err.Message}", $"{err.Source}.{err.TargetSite.Name}", MessageBoxButton.OK, MessageBoxImage.Error); } finally { Cursor = Cursors.Arrow; } }
public bool KeyTransferNode(SpendTx spend, string toKey, string cashCodeFrom, string cashCodeTo) { try { string paymentRef = string.Empty; paymentRef = $"{spend.FromKey} -> {toKey}"; foreach (var tx in spend.Transactions) { Money minerFee = tx.MinerFee; for (int i = 0; i < tx.TxIds.Count; i++) { TxId input = tx.TxIds[i]; Money moneyOut = input.MoneyOut; if (i == tx.TxIds.Count - 1) { moneyOut -= tx.ChangeAmount; } NodeCash.proc_TxPayOutTransfer ( tx.PaymentAddress, $"{input.TransactionId}", moneyOut.ToUnit(MoneyUnit.MilliBTC), minerFee.ToUnit(MoneyUnit.MilliBTC), cashCodeFrom, paymentRef ); minerFee = minerFee <= moneyOut ? Money.Zero : minerFee - moneyOut; } foreach (var output in tx.Tx.Outputs) { string toAddress = $"{output.ScriptPubKey.GetDestinationAddress(GetNetwork)}"; string toTxId = $"{tx.Tx.GetHash()}"; NodeCash.proc_ChangeTxAdd ( toAddress, toTxId, (short)TxStatus.UTXO, output.Value.ToUnit(MoneyUnit.MilliBTC), 0, spend.TxMessage ); if (toAddress == spend.ChangeAddress) { paymentRef = $"{spend.FromKey} -> {spend.FromKey}"; } else { paymentRef = $"{spend.FromKey} -> {toKey}"; } TxPayIn(toAddress, toTxId, string.Empty, cashCodeTo, DateTime.Now, paymentRef); } } return(true); } catch (Exception err) { Console.WriteLine($"Error: {err.Message}"); return(false); } }
public KeyTx(SpendTx spend, ExtKey spendKey, ExtKey changeKey, Money minerFee) { Spend = spend; MinerFee = minerFee; PaymentAddress = spendKey.PrivateKey.GetWif(Spend.Api.Network).GetAddress(ScriptPubKeyType.Legacy).ToString(); Tx = Transaction.Create(Spend.Api.Network); var ReceiverAddress = BitcoinAddress.Create(Spend.ToAddress, Spend.Api.Network); Tx.Outputs.Add(SpendAmount, ReceiverAddress.ScriptPubKey); Tx.Outputs.Add(ChangeAmount, changeKey.PrivateKey.GetWif(Spend.Api.Network).GetAddress(ScriptPubKeyType.Legacy).ScriptPubKey); if (Spend.TxMessage.Length > 0) { Tx.Outputs.Add(Money.Zero, TxNullDataTemplate.Instance.GenerateScriptPubKey(Encoding.UTF8.GetBytes(Spend.TxMessage))); } GetTransactions(spendKey); List <TxId> inputs = new List <TxId>(); foreach (var txId in TxIds) { if (!AddTransaction(spendKey, txId)) { continue; } else { inputs.Add(txId); } var totalSpend = Spend.SpendAmount + TxInAmount - MinerFee; var remainingAmount = Spend.TargetAmount - totalSpend; SpendAmount = remainingAmount > Money.Zero ? TxInAmount - MinerFee : TxInAmount - MinerFee + remainingAmount; ChangeAmount = TxInAmount - SpendAmount - MinerFee; if (Spend.TargetAmount <= (Spend.TxInAmount + TxInAmount - Spend.MinerFee - MinerFee)) { break; } } List <TxId> unusedTx = TxIds.Where(tx => !inputs.Contains(tx)).ToList(); foreach (var tx in unusedTx) { TxIds.Remove(tx); } Tx.Outputs.Clear(); Tx.Outputs.Add(SpendAmount, ReceiverAddress.ScriptPubKey); if (ChangeAmount > Money.Zero) { Tx.Outputs.Add(ChangeAmount, changeKey.PrivateKey.GetWif(Spend.Api.Network).GetAddress(ScriptPubKeyType.Legacy).ScriptPubKey); } if (Spend.TxMessage.Length > 0) { Tx.Outputs.Add(Money.Zero, TxNullDataTemplate.Instance.GenerateScriptPubKey(Encoding.UTF8.GetBytes(Spend.TxMessage))); } Tx.Sign(spendKey.PrivateKey.GetBitcoinSecret(Spend.Api.Network), coins.ToArray()); }
public SpendConfirmWindow(SpendTx spend) { spendTx = spend; InitializeComponent(); }