This is a somewhat simplified version of our SpendMoney function, which will handle someone who initiates a Bitcoin.Spend message. All you really need to do is supply the amount you want to spend, but, of course, this is far from production-ready code, so one of your exercises at the end of the chapter will be to widen this and the spend and receipt messages to fit your needs:
private void SpendMoney()
{
#region IMPORT PRIVKEY
var bitcoinPrivateKey = new BitcoinSecret("cSZjE4aJNPpBtU6xvJ6J4iBzDgTmzTjbq8w2kqnYvAprBCyTsG4x");
var network = bitcoinPrivateKey.Network;
#endregion
var address = bitcoinPrivateKey.GetAddress();
var client = new QBitNinjaClient(network);
var transactionId = uint256.Parse("e44587cf08b4f03b0e8b4ae7562217796ec47b8c91666681d71329b764add2e3");
var transactionResponse = client.GetTransaction(transactionId)?.Result;var receivedCoins = transactionResponse?.ReceivedCoins;OutPointoutPointToSpend = null;
foreach (var coin in receivedCoins)
{
if (coin.TxOut?.ScriptPubKey == bitcoinPrivateKey.ScriptPubKey)
{
outPointToSpend = coin.Outpoint;
}
}
if (outPointToSpend== null)
throw new Exception("TxOut doesn't contain our ScriptPubKey");
var transaction = new Transaction();
transaction.Inputs?.Add(new TxIn()
{
PrevOut = outPointToSpend
});
var hallOfTheMakersAddress = new BitcoinPubKeyAddress("mzp4No5cmCXjZUpf112B1XWsvWBfws5bbB");
// How much you want to TO
var hallOfTheMakersAmount = new Money((decimal) 0.5, MoneyUnit.BTC);
var minerFee = new Money((decimal) 0.0001, MoneyUnit.BTC);
// How much you want to spend FROM
var txInAmount = (Money) receivedCoins[(int) outPointToSpend.N]?.Amount;
Money changeBackAmount = txInAmount - hallOfTheMakersAmount - minerFee;
TxOut hallOfTheMakersTxOut = new TxOut()
{
Value = hallOfTheMakersAmount,
ScriptPubKey = hallOfTheMakersAddress.ScriptPubKey
};
TxOut changeBackTxOut = new TxOut()
{
Value = changeBackAmount,
ScriptPubKey = bitcoinPrivateKey.ScriptPubKey
};
transaction.Outputs?.Add(hallOfTheMakersTxOut);
transaction.Outputs?.Add(changeBackTxOut);
var message = "Our first bitcoin transaction together!";
var bytes = Encoding.UTF8.GetBytes(message);
transaction.Outputs?.Add(new TxOut()
{
Value = Money.Zero,
ScriptPubKey = TxNullDataTemplate.Instance?.GenerateScriptPubKey(bytes)
});
// It is also OK:
transaction.Inputs[0].ScriptSig = bitcoinPrivateKey.ScriptPubKey;
transaction.Sign(bitcoinPrivateKey, false);
BroadcastResponse broadcastResponse = client.Broadcast(transaction)?.Result;
BitcoinSpendReceipt r = new BitcoinSpendReceipt();
if (!broadcastResponse.Success)
{
logger?.LogError($"ErrorCode: {broadcastResponse.Error.ErrorCode}");
logger?.LogError("Error message: " + broadcastResponse.Error.Reason);
r.success = false;
}
else
{
logger?.LogInformation("Success! You can check out the hash of the transaction in any block explorer:");
logger?.LogInformation(transaction.GetHash()?.ToString());
r.success = true;
}
r.time = SystemClock.Instance.GetCurrentInstant().ToDateTimeUtc();
r.amount = txInAmount.ToDecimal(MoneyUnit.BTC);
Bus.Publish(r, "Bitcoin");
}
}
We've highlighted the portions of code that are used to publish the spend receipt message that everyone will be listening for. In a production-ready system, I could see a management role (microservice manager) that listens for the actual spending request message and approves or rejects it prior to sending it to the microservice.