Table of Contents
Important Note
If you would like to use it in production, get in touch with me. As long as nobody is using it in production, I will keep changing it according to my needs.
Introduction
Developer time is money. This guide is an ideal quick start to Bitcoin for C# developers.
I am developing a Bitcoin wallet, called HiddenWallet. The HiddenBitcoin library is the introduction of another abstraction layer between NBitcoin and my user interface.
By the end of this three part tutorial, you will be able to build a Bitcoin wallet.
Quote:
While programming to an API can assist in getting an application up quickly, the developer is limited to innovations that can take place against the API.
Nicolas Dorier, Bitcoin core developer, creator of NBitcoin, the C# Bitcoin library. Keep this quote in mind while using my high-level API.
He is also the main author of the C# Bitcoin book, what I am co-authoring.
How high level is it? In my opinion, a GUI developer, designer should not be able to make too many mistakes. They should not know about inputs and outputs and scriptpubkeys. They should stick at the addresses, privatekeys and wallets level. Also NBitcoin should be fully abstracted away.
If you are familiar with NBitcoin, you can find a deeper level version of this tutorial as a case study in the C# Bitcoin book.
How to Monitor Addresses?
The Blockchain
The Bitcoin Blockchain is a public ledger, so everyone can see every transaction that ever happened there. One can submit a transaction anytime. However at this point, the transaction is not confirmed, it is possible if the added transaction fee is too low the confirmation does not happen. A set of transaction confirms every 10 minutes.
Address Balances
It is very straightforward how you can get a balance of an address:
var network = Network.MainNet;
var httpMonitor = new HttpMonitor(network);
AddressBalanceInfo balanceInfo = httpMonitor.GetAddressBalanceInfo("1ENCTCkqoJqy2XZ2m2Dy1bRax7hsSnC5Fc");
Console.WriteLine($"Address balance: {balanceInfo.Balance}");
Console.WriteLine($"Confirmed balance: {balanceInfo.Confirmed}");
Console.WriteLine($"Unconfirmed balance: {balanceInfo.Unconfirmed}");
There are multiple ways to access The Blockchain, through HTTP API, SPV of full node.
Currently HiddenBitcoin is capable of HTTP, so let's not care about the rest for now.
Note:
I have done an SPV implementation too, but there were too many problems, so I decided not go down on that road for now.
A full-node is very cumbersome to run and it is not getting better. Although I think the code should be straightforward to implement, my audience for HiddenWallet are normal users, not companies, not developers and they will never be running a full-node.
That being said, I will implement it to HiddenBitcoin, but it is not a priority right now.
An other important note: Balance
= Confirmed
+ Unconfirmed
. It means, the unconfirmed balance can be positive or negative, for example if you send some money from the address.
Address History
AddressHistory history = httpMonitor.GetAddressHistory("1ENCTCkqoJqy2XZ2m2Dy1bRax7hsSnC5Fc");
Console.WriteLine("Number of transactions: " + history.Records.Count);
var allTransactionsConfirmed = true;
foreach (AddressHistoryRecord record in history.Records)
{
Console.WriteLine(record.TransactionId + " : " + record.Amount);
allTransactionsConfirmed = allTransactionsConfirmed && record.Confirmed;
}
Console.WriteLine("All transactions are confirmed: " + allTransactionsConfirmed);
Console.WriteLine("Total received - Total spent = Balance");
Console.WriteLine(history.TotalReceived + " - " + history.TotalSpent + " = " +
(history.TotalReceived - history.TotalSpent));
How to Monitor Transactions?
A transaction can have multiple inputs and multiple outputs.
TransactionInfo transactionInfo1 = httpMonitor.GetTransactionInfo(history.Records.First().TransactionId);
Console.WriteLine("txid: " + transactionInfo1.Id);
Console.WriteLine("Network: " + transactionInfo1.Network);
Console.WriteLine("Confirmed: " + transactionInfo1.Confirmed);
Console.WriteLine("Total amount of all inputs: " + transactionInfo1.TotalInputAmount);
Console.WriteLine("Total amount of all outputs: " + transactionInfo1.TotalOutputAmount);
Console.WriteLine("Fee : " + transactionInfo1.Fee);
Console.WriteLine(Environment.NewLine + "Input addresses and amounts: ");
foreach (var input in transactionInfo1.Inputs)
{
Console.WriteLine(input.Amount + " " + input.Address);
}
Console.WriteLine(Environment.NewLine + "Output addresses and amounts: ");
foreach (var output in transactionInfo1.Outputs)
{
Console.WriteLine(output.Amount + " " + output.Address);
}
There are some transctions my API does not care about, let's call them exotic ones, here is how you can handle them:
TransactionInfo transactionInfo2 =
httpMonitor.GetTransactionInfo("8bae12b5f4c088d940733dcd1455efc6a3a69cf9340e17a981286d3778615684");
Console.WriteLine(transactionInfo2.Id);
Console.WriteLine("There are exotic inputs or outputs, so not all of them have been added successfully: "
+ Environment.NewLine + !transactionInfo2.AllInOutsAdded);
What's Next?
During the next lesson, I am going to show you how you can monitor the Safe, I have introduced you in the first part.
License agreement
If you do not like my tutorial or code you are obligated to do a Cersei Lannister walk of shame.
Moreover after your death I will be entitled to take away your soul.