WavesCS - C# client library for Waves API


#1

Hi, all

Let’s discuss WavesCS library in this topic. All the questions, issues, development proposals.

GitHub repo: https://github.com/wavesplatform/WavesCS


#2

We have recently done following changes:

  1. Refactored a lot of code, divided Node class into separate Node and Matcher classes
  2. Downgraded to .NET 4.5.1 to increase backward compatibility
  3. Introduced MassTransfer transaction

I also suggest following change: Convert all the balances from long to decimal automatically taking into account number of digits of specific asset. To do this library should be able to fetch asset details automatically via API.


#3

Just supported new format of DataTransaction and added possibility to put string value.


#4

Hello!

I’ve been learning Unity 3d and I’m a relatively new programmer. I am learning fast though and I think its very fun. As you probably know unity is all about C#. Is there any direction you can lead me so I can integrate waves into unity? I believe that tokens and gaming are made for eachother and if waves can tap into the dev community of unity (hundreds of thousands of developers), it will blow up adoption big time.

Thanks for reading and thanks for what you are doing. Any thoughts on Unity 3d and waves personally?


#5

We have a plan to integrate this lib with Unity and provide SDK. So you can try now to use it in your Unity project and we can discuss here if you can any issues - we can help you to fix them.


#6

Just realized that we need to get rid of System.Web.Script.Serialization.JavaScriptSerializer (which is used for Json parsing) to be compatible with Unity. Unity has it’s own serializer, but I’m not sure that it will be compatible with everything. Maybe we can use diferent serializers in different runtimes.


#7

Just update the library

Now it works with decimal type for amounts instead of longs. So all methods require an instance of Asset class which knows how many digits has particular asset, e.g. if I want to transfer 8.5 waves I write:

node.Transfer(account, recipient, Assets.WAVES, 8.5m);

To transfer 500 tokens of custom asset I can do following (it’s automatically converted to 5000000000 if asset has 8 digits):

var asset = node.GetAsset("4uK8i4ThRGbehENwa6MxyLtxAjAo1Rj9fduborGExarC")
node.Transfer(account, recipient, asset, 500)

It calculates fee automatically for all transaction types, so no need to specify, but it’s still possible.

Serialization logic moved to Transaction class hierarchy, so instead of working with shortcuts like node node.Transfer() you can do following for all transaction types:

var tx = new TransferTransaction(sender.PublicKey, recipient, asset, amount, message);
tx.Sign(sender);                                   
node.Broadcast(tx);

Transactions have method GetBody(), GetJson(), GetJsonWithSignature(), Sign(), etc… Here is an example of transaction implementation.


#8

Hi alexkof,

Good stuff. Very clean API. Quick question though regarding the new DataTransaction class. How do you read the data back out? I can see how to add data to the blockchain …

var data = new Dictionary<string, object>();
// .. populate

var tx = new DataTransaction(Accounts.Alice.PublicKey, data);
tx.Sign(Accounts.Alice);            
var res = node.Broadcast(tx.GetJsonWithSignature());

But now I want to access the blockchain and read back the data into C# Dictionary<string, object>.

Best,
Toyin.


#9

Data can be downloaded by address via API:

https://testnode1.wavesnodes.com/addresses/data/3N4dVn8BsNtsPwZ3MuSWpvBoFXiF3KtRTK8

Implemented Node.GetAddressData() method, please check this test for example.


#10

Switched to Newtonsoft.Json lib to parse Json. Now should work with .NET Core / Mono, but not sure about Unity.


#11

Many thanks for this.


#12

Hierarchical Key (BIP 32)

In addition, is there any functionality to be able to access some sort of Hierarchical Key generator for your blockchain?

Basically I’m looking at having some sort of Deterministic HierarchicalPrivateKey class that can generate PrivateKeyAccount objects. This way, I do not have to manage a collection of private/public key pairs. I just need one HierarchicalPrivateKey generator object and paths to generate deterministic PrivateKeyAccount objects.

Something similar to the ExtKey class from NBlockchain.

What is the purpose of the “nonce” parameter of the PrivateKeyAccount.CreateFromSeed() method?

Best,
Toyin Akin


#13

That’s exactly what you need.


#14

Awesome, thanks. I will have a play.

It would be good to add a test case showing this (Hierarchical PrivateKeys via nonces) …


#15

Just implemented support for SetScriptTransaction which allows create Smart Accounts. For now this is available on testnet only.

There is a test which compiles and sets simplest script to an account, and then removes it:


#16

Added MultiSig test + limited support of versioned transactions. 2nd version of transfer transaction allows to put several proofs instead of single signature. This version specially activated for this test, by default 1st version (now working on MainNet) is used.

[TestMethod]
public void MultisigTest()
{
  // This test works with tranfer transactions of version 2 only
  TransferTransaction.Version = 2;
  var node = new Node();            

  var script = [email protected]"                
    let aliceSigned = sigVerify(tx.bodyBytes, tx.proofs[0], base58'{Accounts.Alice.PublicKey.ToBase58()}')
    let bobSigned   = sigVerify(tx.bodyBytes, tx.proofs[1], base58'{Accounts.Bob.PublicKey.ToBase58()}')
    aliceSigned && bobSigned";
            
  Console.WriteLine($"Scrit: {script}");
            
  var compiledScript = node.CompileScript(script);
            
  var multiAccount = PrivateKeyAccount.CreateFromSeed(PrivateKeyAccount.GenerateSeed(), AddressEncoding.TestNet);           
  Console.WriteLine("Account generated: {0}", multiAccount.Address);
  node.Transfer(Accounts.Alice, multiAccount.Address, Assets.WAVES, 0.1m);
            
  Thread.Sleep(10000);
            
  Assert.IsTrue(node.GetBalance(multiAccount.Address) == 0.1m);
            
  var setScriptTx = new SetScriptTransaction(multiAccount.PublicKey, compiledScript, 'T');            
  setScriptTx.Sign(multiAccount);
  node.Broadcast(setScriptTx.GetJsonWithSignature());

  Thread.Sleep(10000);
            
  var tx = new TransferTransaction(multiAccount.PublicKey, Accounts.Alice.Address, Assets.WAVES, 0.09m, 0.005m);
  tx.Sign(Accounts.Alice, 0);
  tx.Sign(Accounts.Bob, 1);

  node.Broadcast(tx);
            
  Thread.Sleep(10000);
            
  Assert.IsTrue(node.GetBalance(multiAccount.Address) < 0.02m);
}

WavesJ: Waves + Java library
#17

Nicely done on this library @alexkof

I am currently trying to retrieve transaction history of a specific address, similar to Rest-API method GET /transactions/address/{address}/limit/{limit}. However, I couldn’t find any ways to perform that using this library.

I have tried using node.GetObject(“transactions/address/{0}/limit/10”, account.Address); but it returns an error due incompatible json deserialization.

What is the correct way to do it?

Thanks.


#18

Hi, just added GetTransactionsByAddress() method, check this test:

[TestMethod]
public void TestGetTransactions()
{
  var node = new Node();
  var transactions = node.GetTransationsByAddress(Accounts.Alice.Address, 10);
	
  Assert.IsTrue(transactions.Count() == 10);
  Assert.IsTrue(transactions.All(t => t.GetInt("type") < 20));
  Assert.IsTrue(transactions.All(t => t.GetString("sender").Length > 30));
}

Also, we have pending pull-request with more strong method which parses all transaction types.


#19

Hi, this is my PR to WavesCS library: https://github.com/wavesplatform/WavesCS/pull/15/commits

I just add SponsoredFeeTransaction and tests for it + tests for IssueTransaction, ReissueTransaction and BurnTransaction


#20

Good day @alexkof, thanks for the Csharp version. it has helped improved my understanding greatly even though I a newbie in BC (blockchain).

Please help me understand how the account is created in BC, I am am following the AccountTest.TestAccountCreation specifically this part PrivateKeyAccount.CreateFromSeed(seed2, AddressEncoding.TestNet); I don’t seem to understand how the address is created in BC, which line of code does the creation, is it hidden? From what I could see is that the Privatekey, Publickey and Address is generated by libraries in the libs folder. Are the libs libraries communicate with Blockchain?

Thanks in advance.