Skip to content

miguel1117/Nano.Net

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Nano.Net

A .NET library for building projects with nano. Still in development.
Please feel free to submit any changes, bugfixes or new features using the issues/pull requests feature here on GitHub.
This project follows Semantic Versioning.

Features/Roadmap

  • Seed generation and derivation
  • Keypair and address generation
  • Local block signing
  • Unit conversion
  • RPC client for interacting with the network
  • Custom address prefix support (e.g., ban_)
  • WebSockets support

Requirements

Nano.Net targets .NET Standard 2.0, which supports most .NET implementations.

Installation

Nano.Net builds are available on Nuget, and can be added to your project by running

dotnet add package Nano.Net

Alternatively, you can compile the project yourself.

Usage

Using the RPC client

var rpcClient = new RpcClient(nodeAddress);

AccountInfoResponse accountInfo = await rpcClient.AccountInfoAsync("nano_3r9rdhbipf9xsnpxdhf7h7kebo8iyfefc9s3bcx4racody5wubz1y1kzaon9");
Console.WriteLine($"Balance (raw): {accountInfo.Balance}");
Console.WriteLine($"Representative: {accountInfo.Representative}");

Account creation and seed derivation

// There are Account constructors overloads available that accept
// private keys/seeds encoded as hex strings and byte arrays.

// Create a new Account object with a randomly generated private key
Account account1 = new Account();

// Generate a random hex seed and create an Account using it and an index.
string randomSeed = Utils.GenerateSeed();
Account account2 = new Account(randomSeed, 5);

// Create an Account from a private key.
Account account3 = new Account(privateKey: "A066701E0641E524662E3B7F67F98A248C300017BAA8AA0D91A95A2BCAF8D4D8");

Account creation with a custom address prefix

// Specify the prefix.
Account account = new Account("ban");

Key and address conversion

// Private key from a seed and index
byte[] privateKey = Utils.DerivePrivateKey("949DD42FB17350D7FDDEDFFBD44CB1D4DF977026E715E0C91C5A62FB6CA72716", index: 5);
            
// Public key from private key
byte[] publicKey = Utils.PublicKeyFromPrivateKey(privateKey);
            
// Convert from address to public key or in reverse
string address = Utils.AddressFromPublicKey(publicKey);
publicKey = Utils.PublicKeyFromAddress(address);

Sending and receiving a transaction

var rpcClient = new RpcClient(nodeAddress);
Account account = new Account(privateKey: "A066701E0641E524662E3B7F67F98A248C300017BAA8AA0D91A95A2BCAF8D4D8");
            
// Sets the balance, representative and frontier for this account from a node. Can also be set manually.
await rpcClient.UpdateAccountAsync(account);

// Generate a PoW nonce using the node rpcClient is connected to.
// Note: public nodes usually have the work generation rpc command disabled, so you will need to use your own node.
WorkGenerateResponse workResponse = await rpcClient.WorkGenerateAsync(account.Frontier);
string pow = workResponse.Work;
            
// Creates a block and automatically sign it. The PoW nonce has to be obtained externally.
Block sendBlock = Block.CreateSendBlock(account,
    "nano_3tjhazni9juaoa8q9rw33nf3f6i45gswhpzrgrbrawxhh7a777ror9okstch",
    Amount.FromRaw("1"), 
    pow);
            
// Publish the block to the network.
await rpcClient.ProcessAsync(sendBlock);

// Receive a transaction
await rpcClient.UpdateAccountAsync(account); // account data should be updated before publishing a block
workResponse = await rpcClient.WorkGenerateAsync(account.Frontier);
pow = workResponse.Work;

Block receiveBlock = Block.CreateReceiveBlock(account, "BCB03523591F42792EAF315676FF944D3530C0F1A38F55066BDF26EA15B7073A", 
    Amount.FromRaw("1"), pow); // you can also get pending blocks for an account using the rpc client and use a PendingBlock object as an argument.
await rpcClient.ProcessAsync(receiveBlock);

WebSockets usage

  • Note: if you're using a public node you should be aware that some of them may:
    • Have WebSocket support disabled.
    • Behave differently than the "vanilla" nano node behaviour. In those cases, NanoWebSocketClient may not work as expected.
// Connect to a websocket enpoint.
var w = new NanoWebSocketClient(nodeAddress);

// Subscribe to a topic. Some topics may have options. Topics can be found in the WebsSockets/Topics directory.
w.Subscribe(new ConfirmationTopic());

// Subscribe to the catch-all event, which will send messages for all topics the client receives.
w.Message += (client, content) => { Console.WriteLine(content); };

// Subscribe to the Confirmation topic event.
w.Confirmation += (client, message) => { Console.WriteLine(message.Message.Amount); };

// Don't forget to run Start() to actually start receiving the messages.
await w.Start();

Acknowledgements

  • NanoDotNet for bits of code, including the Nano base32 implementation
  • Chaos.NaCl for the original C# implementation of ED25519 signing and keypair generation
  • BLAKE2 for the C# implementation of Blake2B
  • BigDecimal for an arbitrary precision decimal for .NET

Donations

This library is 100% free, but donations are accepted at the address below. Any amount is appreciated. nano_3h71hnsc5asdsd9qfetxwr6do7ebkyef6ufwbybfbh3z7itts6wym5b4tg7x