Tezos C# SDK Netezos: forge an operation locally and sign it using Ledger wallet

Netezos is a .NET Standard 2.0 library for working with Tezos blockchain. In this blog post, find the use cases of working with local forging and Tezos Ledger

Dmitry
Dmitry   Follow

Netezos is a .NET Standard 2.0 library for working with Tezos. In this blog post, we’ll show you use cases of working with local forging and Tezos Ledger App.

# Installation

Netezos.Forge (opens new window) and Netezos.Ledger (opens new window) packages are available on NuGet, a package manager for .NET developers. Thus, you can install the packages via the Nuget Package Manager GUI or the following commands:

PM> Install-Package Netezos.Forge
PM> Install-Package Netezos.Ledger

Or simply clone a project from the GitHub repository:

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

# Getting a public key from the ledger

First of all, we will connect to the ledger and get the address from it.

var ledger = (await TezosLedgerClient.GetHIDLedgersAsync()).First();
var pubKey = await ledger.GetPublicKeyAsync();
Console.WriteLine($"Public key: {pubKey.Address}");

Let’s go to the Faucet Bot (opens new window) 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.

# Sending operations

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

var rpc  = new TezosRpc("https://rpc.tzkt.io/babylonnet");
var head = rpc.Blocks.Head;
var contract = head.Context.Contracts[pubKey.Address];
var branch = await head.Hash.GetAsync<string>();
var counter = await contract.Counter.GetAsync<int>();
var manager = await contract.ManagerKey.GetAsync<string>();

Then we can prepare list of operation content

var content = new List<ManagerOperationContent>();
if (string.IsNullOrEmpty(manager))
{
    content.Add(new RevealContent
    {
        Source = pubKey.Address,
        Fee = 1267,
        Counter = ++counter,
        GasLimit = 10100,
        StorageLimit = 0,
        PublicKey = pubKey.GetBase58()
    });
}
content.Add(new TransactionContent
{
    Source = pubKey.Address,
    Fee = 1287,
    Counter = ++counter,
    GasLimit = 13805,
    StorageLimit = 326,
    Amount = 100,
    Destination = "tz1KhnTgwoRRALBX6vRHRnydDGSBFsWtcJxc"
});

And now the most interesting thing. Let’s make our transaction really safe. We’ll use a local forging because we don’t trust anyone:

var operationBytes = await new LocalForge().ForgeOperationGroupAsync(branch, content);

Next, we make it even safer and send it to the ledger for signing:

var signatureBytes = await ledger.Sign(Hex.Parse("03").Concat(operationBytes));

And finally, we can send it to the node to inject an operation:

var opHash = await 
  rpc.Inject.Operation.PostAsync(Hex.Convert(operationBytes.Concat(signatureBytes)));
Console.WriteLine(opHash);

Here we go! Now we can check the hash of the operation: https://babylon.tzkt.io/oojc52Qhi7Bzr3fp9Xkb4DWs9jSZ5kFwkf518LYACwRNahmAgui (opens new window)

Automatic content filling is currently in work, also we will provide more documentation for Netezos, so stay with us!

We would also like to remind you that Netezos is an open-developing (opens new window) project, and any kind of contribution is highly appreciated!

Cheers!