A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://programmingblockchain.gitbooks.io/programmingblockchain/content/wallet/web-api.html below:

Web API/ Block Explorer | Programming The Blockchain in C#

Web API/ Block Explorer | Programming The Blockchain in C#
  1. Create your own wallet
Web API/ Block Explorer

Block explorers, or more specifically the web APIs, usually provided by block explorers can get you started very quickly. You used QBitNinja already in this book, but many more exist. A block explorer is a self-hosted or third-party hosted solution which provides you information about blocks, transactions and addresses in the chain.

Explorer

A block explorer connects to a bitcoin node, indexes the data of the blockchain and exposes an easy to use API. Solutions include: QBitNinja, Blockcypher, Smartbit, Electrum server, Insight, NBXplorer.

The advantages are:

The disadvantages are:

Different block explorers expose different APIs and features. For example most block explorers use HTTP web APIs, while Electrum uses the Stratum protocol. Block explorers never have the private keys of the wallet.

With QBitNinja, it is difficult to track a wallet which always changes addresses, because you need to poll all the addresses belonging to the same wallet to detect any change.

However, Electrum or NBXplorer and SmartBit exposes notifications via websockets or long polling so you don't need to poll all the addresses of the wallet. Insight is not well maintained. Blockcypher, QBitNinja and Smartbit are third-party hosted. If you are interested in building a wallet such way take a look at nopara73's CodeProject article: Build your own Bitcoin wallet with QBitNinja in C# .

NBxplorer has been created to have a very simple API, is self hostable, and tracks only what is needed for your wallet. Contrary to QBitNinja, it relies on you having a full node, but it provides websocket notifications and an easy way to query the balances of a wallet.

NBXplorer is also multi crypto currency on a single server. As of October 2018, it supports Bitcoin, Litecoin, BCash, BGold, Dash, Dogecoin, Dystem, Feathercoin, Groestlcoin, Monacoin, Polis, UFO, Viacoin and Zclassic. It integrates seamlessly with NBitcoin.

To setup NBXplorer, you need a fully synced bitcoind node with default parameters. Then clone and run NBXplorer with default parameters.

Reference the NBXplorer.Client nuget package then you need to notify the NBXplorer to track the user wallet:

var network = new NBXplorerNetworkProvider(NetworkType.Mainnet).GetBTC();
var userExtKey = new ExtKey();
var userDerivationScheme = network.DerivationStrategyFactory.CreateDirectDerivationStrategy(userExtKey.Neuter(), new DerivationStrategyOptions()
{
    // Use non-segwit
    Legacy = true
});
ExplorerClient client = new ExplorerClient(network);
client.Track(userDerivationScheme);

Change NetworkType.Mainnet if you want to use Testnet or Regtest.

If you want a new unused address:

Console.WriteLine(client.GetUnused(userDerivationScheme, DerivationFeature.Deposit).Address);

Then you can query the UTXOs of your user and spend them the following way:

var utxos = client.GetUTXOs(userDerivationScheme, null, false);

If you want to spend those UTXOs:

var coins = utxos.GetUnspentCoins();
var keys = utxos.GetKeys(userExtKey);
TransactionBuilder builder = Network.Main.CreateTransaction();
builder.AddCoins(coins);
builder.AddKeys(keys);
builder.Send(new Key(), Money.Coins(0.5m));
builder.SetChange(changeAddress.ScriptPubKey);

// Set the fee rate
var fallbackFeeRate = new FeeRate(Money.Satoshis(100), 1);
var feeRate = tester.Client.GetFeeRate(1, fallbackFeeRate).FeeRate;
builder.SendEstimatedFees(feeRate);
/////

var tx = builder.BuildTransaction(true);
Console.WriteLine(client.Broadcast(tx));

A problem with this solution is that if you call this code twice at the exact same time, you will likely broadcast two transactions spending the same coins, resulting in one of the transaction getting dropped.

To prevent this problem, you need to make sure to not spend twice the same coins.

A way to solve the problem is by simply retrying:

while(true)
{    
    var coins = utxos.GetUnspentCoins();
    var keys = utxos.GetKeys(userExtKey);
    TransactionBuilder builder = Network.Main.CreateTransactionBuilder();
    builder.AddCoins(coins);
    builder.AddKeys(keys);
    builder.Send(new Key(), Money.Coins(0.5m));
    builder.SetChange(changeAddress.ScriptPubKey);

    // Set the fee rate
    var fallbackFeeRate = new FeeRate(Money.Satoshis(100), 1);
    var feeRate = tester.Client.GetFeeRate(1, fallbackFeeRate).FeeRate;
    builder.SendEstimatedFees(feeRate);
    /////

    var tx = builder.BuildTransaction(true);
    var result = client.Broadcast(tx);
    if(result.Success)
    {
        Console.WriteLine("Success!");
        break;
    }
    else if(result.RPCCode.HasValue && result.RPCCode.Value == RPCErrorCode.RPC_TRANSACTION_REJECTED)
    {
        Console.WriteLine("We probably got a conflict, let's try again!");
        continue;
    }
    else
    {
        Console.WriteLine($"Something is really wrong {result.RPCCode} {result.RPCCodeMessage} {result.RPCMessage}");
        // Do something!!!
    }
}

Another common way is to have a global list of already used outpoint that you can check against.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4