Skip to content

Latest commit

 

History

History
221 lines (160 loc) · 6.96 KB

File metadata and controls

221 lines (160 loc) · 6.96 KB

Counter tutorial with C# and Casper .NET SDK

This example is based on the Counter contract tutorial available in the Casper Network web site.

Using the Casper .NET SDK, we'll show you how to:

  • Send $CSPR from one account to another.
  • Deploy the counter contract example to the blockchain.
  • Read the counter value.
  • Call the counter_inc contract entry point to increase the counter.

NOTE: We use a local network in this example. Learn here how to install your own local network. Alternatively, you can easily adapt the code in this example to use the casper-test network. In this case, skip the transfer from faucet step.

Step 1. Get a new instance of the Casper client

Prepare an instance of the client and a couple of keys that will be used during the example:

static string nodeAddress = "http://207.154.217.11:11101/rpc";
static string chainName = "casper-net-1";

static NetCasperClient casperSdk = new NetCasperClient(nodeAddress);

static KeyPair faucetAcct = KeyPair.FromPem("/tmp/faucetact_sk.pem");

static KeyPair myAccount = KeyPair.FromPem("/tmp/myaccount_sk.pem");
static PublicKey myAccountPK = PublicKey.FromPem("/tmp/myaccount_pk.pem");

Step 2. Send $CSPR from the faucet account to myAccount

Use the StandardTransfer template to create a deploy object that orders a transfer of 2500 $CSPR from the faucet account. Sign it and send it to the network.

Take the deploy_hash from the response and make a call to GetDeploy with a timeout of 120 seconds. This will query the network until the transfer is complete.

public static async Task FundAccount()
{
  var deploy = DeployTemplates.StandardTransfer(
      faucetAcct.PublicKey,
      myAccountPK,
      2500_000_000_000,
      100_000_000,
      chainName);
  deploy.Sign(faucetAcct);
  
  var putResponse = await casperSdk.PutDeploy(deploy);
  
  var deployHash = putResponse.GetDeployHash();
  
  var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(120));
  var getResponse = await casperSdk.GetDeploy(deployHash, tokenSource.Token);
  
  var execResult = getResponse.Parse().ExecutionResults.First();
  Console.WriteLine("Deploy COST : " + execResult.Cost);
}

Step 3. Deploy the counter contract

If you haven't done yet, get a copy of the repository and build the contract following the instructions in the README file.

git clone https://github.com/casper-ecosystem/counter
cd counter
make build-contract

As a result you will get the contract compiled at target/wasm32-unknown-unknown/release/. Copy the contract-define.wasm to your working directory.

Next, use the ContractDeploy deploy template to prepare a Deploy object. Sign it and deploy it.

public static async Task DeployContract(string wasmFile)
{
  var wasmBytes = await File.ReadAllBytesAsync(wasmFile);
  
  var deploy = DeployTemplates.ContractDeploy(
      wasmBytes, 
      myAccount,
      50_000_000_000, 
      chainName);
  deploy.Sign(myAccount);
  
  var putResponse = await casperSdk.PutDeploy(deploy);
  
  var deployHash = putResponse.GetDeployHash();
  
  var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(120));
  var getResponse = await casperSdk.GetDeploy(deployHash, tokenSource.Token);
  
  var execResult = getResponse.Parse().ExecutionResults.First();
  
  Console.WriteLine("Deploy COST : " + execResult.Cost);
  Console.WriteLine("Contract key: " + execResult.Effect.Transforms.First(t =>
      t.Type == TransformType.WriteContract).Key);
}

Step 4. Get the counter value

The deploy of the contract creates a Named Key in the caller account named counter. Its key value is the new contract hash.

The contract itself also has a Named Key called count that stores the value of the counter.

Combining both, we form the path counter/count. We can send the QueryGlobalState method to the network to get the current value of the counter.

public static async Task QueryState()
{
  var accountKey = new AccountHashKey(myAccountPK);
  var rpcResponse = await casperSdk.QueryGlobalState(accountKey, null,
     "counter/count");
 
  var result = rpcResponse.Parse();
  Console.WriteLine("Counter value: " + (int)result.StoredValue.CLValue);
}

The response from the network will look like the following:

{
  "api_version": "1.0.0",
  "stored_value": {
    "CLValue": {
      "cl_type": "I32",
      "bytes": "00000000",
      "parsed": 0
    }
  },
  "merkle_proof": "..."
}  

When you know the type of a CLValue you can easily get its value with the corresponding cast operator. In this case, we know the counter is an integer so we can convert the CLValue to an integer number with (int).

In the previous code we queried the network starting from an account key and using a path that hops from the account to the contract and then retrieves the value of the count named key. But you could also query directly the contract using the contract hash:

var contrachHash = "hash-4d6b463f4a5503a1d2fb8dbca92260e3574ff86d68d2103b6d4ecb28246dfb5c";
var response = await casperSdk.QueryGlobalState(contrachHash, null, "count");

var result = response.Parse();
Console.WriteLine("Counter value: " + result.StoredValue.CLValue.ToInt32());

Step 5. Increment the counter

To increment the counter we need to send a deploy and call the counter_inc entry point in the contract. For this, we can use the ContractCall template:

public static async Task CallCounterInc()
{
  var deploy = DeployTemplates.ContractCall(
      "counter",
      "counter_inc",
      null,
      myAccountPK,
      15_000_000,
      chainName);
  deploy.Sign(myAccount);
  
  var putResponse = await casperSdk.PutDeploy(deploy);
  
  var deployHash = putResponse.GetDeployHash();
  
  var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(120));
  var getResponse = await casperSdk.GetDeploy(deployHash, tokenSource.Token);
  
  var execResult = getResponse.Parse().ExecutionResults.First();
  
  Console.WriteLine("Deploy COST : " + execResult.Cost);
}

Step 6. Check the counter has a new value

Calling the QueryState() method in step 4 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 git repository also contains a second contract named counter-call. It is an example of how to increment the counter value with a deploy instead of calling a contract entry point.

Logging handler

The example in Program.cs creates the Casper client passing a logging handler as a reference. This is useful to see the communication exchanged with the node.

To print the logs to the standard output, use:

LoggerStream = new StreamWriter(Console.OpenStandardOutput())

To print the logs to a file, use:

LoggerStream = File.AppendText("netcasper.log")