Tezos C# SDK: Examples of Netezos usage

Cases of using Netezos - a package of .NET Standard libraries for working with Tezos blockchain

Dmitry
Dmitry   Follow

Netezos is a package of .NET Standard 2.0 libraries for working with Tezos. At this stage, Netezos.Rpc and Netezos.Keys are implemented. Let’s dive a little deeper and see how it works.

# Installation

Netezos.Rpc and Netezos.Keys packages are available on NuGet, a package manager for .NET developers. Thus, you can install the packages via the Nuget Package Manager graphical interface or the following command:

PM> Install-Package Netezos.Keys

Or just clone the project from our GitHub repository:

$ git clone https://github.com/baking-bad/netezos

# Let’s get it started!

To get started, we need an account with funds. There are two ways to do this: to activate a new account from a JSON file, or a much simpler way to get money from the Faucet Telegram Bot. Let’s consider both of them.

# Using faucet bot

Let’s generate a new key and get test coins from the telegram bot:

var key = new Key();
Console.WriteLine($"Secret key: {key.GetBase58()}");
Console.WriteLine($"tz Address: {key.PubKey.Address}");

NOTE: Save secret key and tz address, we’ll need them in the next step.

Let’s go to the Faucet Bot and get some test coins. You can use the 🤑 Get coins option to deposit 100 ꜩ to your tz address, or ➕ Add subscription and set Amount to ensure your balance is always non-zero.

# Activation via JSON

First of all, let’s download a JSON file from https://faucet.tzalpha.net/ and parse the data:

var words = new List<string>
{
  "salmon","solar","alone","prosper","almost","length","impose",
  "toilet","edit","seed","curtain","coyote","zoo","unaware","pause"
};
var secret = "693d026e9d3127e781be859bcd13c5cddebfc980";
var password = "XUWmCcdSbP";
var email = "jqlpsrbl.obkysflu@tezos.example.org";

We can use that to extract the private key:

var mnemonic = new Mnemonic(words);
var key = Key.FromMnemonic(mnemonic, email, password);

This is the most frequent use case, but you have multiple options though:

var keyFromBase58 = Key.FromBase58(key.GetBase58());
var bytes = Base58.Parse(key.GetBase58());
var keyFromBytes = Key.FromBytes(bytes);
var hex = Hex.Convert(bytes);
var keyFromHex = Key.FromHex(hex);

Note: Currently we support ed25519 and secp256k1 curves.

Now, that we have received the key, we can activate the account. We will use Netezos.Rpc package for that purpose. Read all about it in this blogpost.

# Account activation

Let’s create a content list for our future operation. The pkh and secret fields are taken from the downloaded JSON file:

var content = new List<object>
{
   new
   {
       kind = "activate_account",
       pkh = key.PubKey.Address,
       secret
   }
};

Then let’s create an RPC object and get the required data from the chain:

var rpc = new TezosRpc("https://rpc.tzkt.io/babylonnet/");
var branch = await rpc.Blocks.Head.Hash.GetAsync<string>();
var opBytes = await rpc.Blocks.Head.Helpers.Forge.Operations.PostAsync<string>(branch, content);

Once we get operation bytes we can sign them with our key and broadcast to the network:

var signedBytes = key.Sign(Hex.Parse("03" + opBytes));
var opHash = await rpc.Inject.Operation.PostAsync(opBytes + Hex.Convert(signedBytes));
Console.WriteLine(opHash);

# Public key revelation

After successful account activation, we will perform the reveal operation.

First, one has to get a fresh counter value and public key hash to build an operation content:

var counter = await Rpc.Blocks.Head.Context.Contracts[key.PubKey.Address].Counter.GetAsync<int>();
var revealContent = new List<object>
{
   new
   {
       kind = "reveal",
       source = key.PubKey.Address,
       fee = "1267",
       counter = (++counter).ToString(),
       gas_limit = "10100",
       storage_limit = "0",
       public_key = key.PubKey.GetBase58()
   }
};

Next steps are similar to the activation operation:

var revealOpBytes = await rpc.Blocks.Head.Helpers.Forge.Operations.PostAsync<string>(branch, revealContent);
var revealSignedBytes = key.Sign(Hex.Parse("03" + revealOpBytes));
var revealOpHash = await Rpc.Inject.Operation.PostAsync(revealOpBytes + Hex.Convert(revealSignedBytes));
Console.WriteLine(revealOpHash);

# Transaction

And finally, we can make a transaction.

Preparing an operation content first:

var balance = await Rpc.Blocks.Head.Context.Contracts[key.PubKey.Address].Balance.GetAsync<long>();
var trContent = new List<object>
{
   new
   {
       kind = "transaction",
       source = key.PubKey.Address,
       fee = "1282",
       counter = (++counter).ToString(),
       gas_limit = "10307",
       storage_limit = "0",
       amount = (balance - 1285).ToString(),
       destination = "tz1KhnTgwoRRALBX6vRHRnydDGSBFsWtcJxc"
   }
};

Taking forge-sign-inject steps:

var trOpBytes = await rpc.Blocks.Head.Helpers.Forge.Operations.PostAsync<string>(branch, trContent);
var trSignedBytes = key.Sign(Hex.Parse("03" + trOpBytes));
var trOpHash = await Rpc.Inject.Operation.PostAsync(trOpBytes + Hex.Convert(trSignedBytes));
Console.WriteLine(trOpHash);

That’s it! Local forging and automatic content fill will be implemented and documented a bit later, so stay tuned.
We would also like to remind you that Netezos is an open-developing project, and any kind of contribution is highly appreciated!

Cheers!