# Counter tutorial with C# and NetCasperSDK
This example shows how to use the NetCasperSDK to:
- send $CSPR from one account to another
- Deploy the counter contract example to the network
- Read the counter value
- Call the `counter_inc` contract function to increase the counter.
We are using a local network. Learn [here](https://docs.casperlabs.io/en/latest/dapp-dev-guide/setup-nctl.html) how to install your own local network.
### Get a new instance of the client
Prepare an instance of the client and a couple of keys that will be used during the example:
```csharp
static string nodeAddress = "http://207.154.217.11:11101/rpc";
static NetCasperClient casperSdk = new NetCasperClient(nodeAddress);
static KeyPair faucetAcct = KeyPair.FromPem("/tmp/faucetact.pem");
static KeyPair account2 = KeyPair.FromPem("/tmp/myaccount2.pem");
```
### Send $CSPR from the faucet account to `account2`
Use the `StandardTransfer` template to create a deploy object that orders a transfer of 2500 $CSPR. Sign it and deploy it to the network.
Take the `deploy_hash` from the response and make a call to `GetDeploy` with a timeout of 120 seconds to obtain the result of the transfer (testnet usually needs a longer timeout).
```csharp
public static async Task FundAccount()
{
var deploy = DeployTemplates.StandardTransfer(
faucetAcct,
account2.PublicKey,
2500000000000,
1200,
"casper-net-1");
deploy.Sign(faucetAcct);
var response = await casperSdk.PutDeploy(deploy);
string deployHash = response.GetDeployHash();
var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(120));
response = await casperSdk.GetDeploy(deployHash, tokenSource.Token);
File.WriteAllText("res_FundAccount.json", response.Result.GetRawText());
}
```
### Deploy the counter contract
You may find more information on the counter contract used in this example here: [A Counter Contract Tutorial](https://docs.casperlabs.io/en/latest/dapp-dev-guide/tutorials/counter/index.html).
If you haven't done yet, clone the repository and build the contract following the instruction in the README file.
```
git clone https://github.com/casper-ecosystem/counter
cd counter
cat README
```
Now use the `ContractDeploy` template to prepare a deploy object, sign it and deploy it.
```csharp
public static async Task DeployContract(string wasmFile)
{
var wasmBytes = System.IO.File.ReadAllBytes(wasmFile);
var deploy = DeployTemplates.ContractDeploy(wasmBytes,
account2, //
500000000000, //payment
"casper-net-1", //network
1, //gas-price
1800000); //ttl
deploy.Sign(account2);
var response = await casperSdk.PutDeploy(deploy);
string deployHash = response.GetDeployHash();
var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(120));
response = await casperSdk.GetDeploy(deployHash, tokenSource.Token);
Console.WriteLine(response.Result.GetRawText());
System.IO.File.WriteAllText("res_DeployContract.json", response.Result.GetRawText());
}
```
### Get the counter value
To get current counter value, call `GetAccountInfo` indicating the path of the key to retrieve:
```csharp
public static async Task QueryState()
{
var response = await casperSdk.GetAccountInfo(account2.PublicKey, new List<string>() {"counter", "count"});
Console.WriteLine(response.Result.GetRawText());
System.IO.File.WriteAllText("res_QueryState.json", response.Result.GetRawText());
}
```
The output will look like the following:
```
{
"api_version": "1.0.0",
"stored_value": {
"CLValue": {
"cl_type": "I32",
"bytes": "00000000",
"parsed": 0
}
},
"merkle_proof": "..."
}
```
Alternatively, the contract hash and the `QueryState` method can be used to get the counter value instead of `GetAccountInfo`:
```csharp
var response = await casperSdk.QueryState(
"hash-d27328ad7692dfb029430d020c7d2c88d4b1d9f2a510c1712df9dbf4be74d85d",
new List<string>() {"count"});
```
### Increment the counter
Next, increment the counter by calling the `counter_inc` method. Use now the `ContractCall` template:
```csharp
public static async Task CallCounterInc()
{
var deploy = DeployTemplates.ContractCall("counter", "counter_inc",
new List<NamedArg>(), account2,
50000000000, "casper-net-1", 1, 1800000);
deploy.Sign(account2);
var response = await casperSdk.PutDeploy(deploy);
string deployHash = response.GetDeployHash();
var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(120));
response = await casperSdk.GetDeploy(deployHash, tokenSource.Token);
Console.WriteLine(response.Result.GetRawText());
System.IO.File.WriteAllText("res_CallCounterInc.json", response.Result.GetRawText());
}
```
### Check the counter has a new value
Calling the `QueryState()` method as above we'll now see that the counter has a new value:
```
{
"api_version": "1.0.0",
"stored_value": {
"CLValue": {
"cl_type": "I32",
"bytes": "01000000",
"parsed": 1
}
},
"merkle_proof": "0300000000989ca079a
```
The tutorial also contains a second contract named `counter-call`. We can increment the count using that second contract instead of the session entry-point we used before. Call the `DeployContract()` function passing now the `contract-call.wasm` location.
### Full example code
`Program.cs`
```csharp=
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using NetCasperSDK;
using NetCasperSDK.JsonRpc;
using NetCasperSDK.Types;
namespace CasperMain
{
public static class DeployCounterContract
{
static string nodeAddress = "http://207.154.217.11:11101/rpc";
static NetCasperClient casperSdk;
static KeyPair faucetAcct = KeyPair.FromPem("/tmp/faucetact.pem");
static KeyPair account2 = KeyPair.FromPem("/tmp/myaccount2.pem");
public static async Task FundAccount()
{
var deploy = DeployTemplates.StandardTransfer(
faucetAcct,
account2.PublicKey,
2500000000000,
1200,
"casper-net-1");
deploy.Sign(faucetAcct);
var response = await casperSdk.PutDeploy(deploy);
string deployHash = response.GetDeployHash();
var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(120));
response = await casperSdk.GetDeploy(deployHash, tokenSource.Token);
File.WriteAllText("res_FundAccount.json", response.Result.GetRawText());
}
public static async Task DeployContract(string wasmFile)
{
var wasmBytes = System.IO.File.ReadAllBytes(wasmFile);
var deploy = DeployTemplates.ContractDeploy(wasmBytes, account2,
500000000000, "casper-net-1", 1, 1800000);
deploy.Sign(account2);
var response = await casperSdk.PutDeploy(deploy);
string deployHash = response.GetDeployHash();
var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(120));
response = await casperSdk.GetDeploy(deployHash, tokenSource.Token);
Console.WriteLine(response.Result.GetRawText());
System.IO.File.WriteAllText("res_DeployContract.json", response.Result.GetRawText());
}
public static async Task QueryState()
{
var response = await casperSdk.GetAccountInfo(account2.PublicKey,
new List<string>() {"counter", "count"});
Console.WriteLine(response.Result.GetRawText());
System.IO.File.WriteAllText("res_QueryState.json", response.Result.GetRawText());
}
public static async Task CallCounterInc()
{
var deploy = DeployTemplates.ContractCall("counter", "counter_inc",
new List<NamedArg>(), account2,
50000000000, "casper-net-1", 1, 1800000);
deploy.Sign(account2);
var response = await casperSdk.PutDeploy(deploy);
string deployHash = response.GetDeployHash();
var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(120));
response = await casperSdk.GetDeploy(deployHash, tokenSource.Token);
Console.WriteLine(response.Result.GetRawText());
System.IO.File.WriteAllText("res_CallCounterInc.json", response.Result.GetRawText());
}
public async static Task Main(string[] args)
{
// use a logginghandler to print out all communication with the node
//
var loggingHandler = new RpcLoggingHandler(new HttpClientHandler())
{
LoggerStream = new StreamWriter(Console.OpenStandardOutput())
};
casperSdk = new NetCasperClient(nodeAddress, loggingHandler);
try
{
await FundAccount();
await DeployContract("/tmp/counter-define.wasm");
await QueryState();
await CallCounterInc();
await QueryState();
await DeployContract("/tmp/counter_call.wasm");
await QueryState();
}
catch (RpcClientException e)
{
Console.WriteLine(e.RpcError.Message);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
```
`CounterContract.csproj`
```xml=
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NetCasperSDK" Version="0.9.2" />
</ItemGroup>
</Project>
```