Skip to main content

Define and Execute Methods with Parameters via the CLI

Useful Applets will invariably have methods that accept arguments, such as "to whom some token should be transferred?", "which domain to register?", and "how many tokens to transfer?".

In this tutorial we'll see how to define methods with parameters and how to pass arguments when invoking such methods using the Weilliptic CLI.

Preparations

This tutorial assumes that

  • you have access to the WeilChain.
  • you have completed the Basic Weil Applet Creation tutorial, as we will improve the Applet created there, and have a shell opened at the root of that project;
  • you have completed the Weil Applet Deployment using wcli tutorial, as we will use wcli in a similar way.

Updating the Counter Applet

We will add a method to set the counter to an arbitrary value, bigger or equal to 0. To add the method to the Counter Applet, edit the counter.widl file to match the following.

counter.widl
interface Counter {
query func get_count() -> uint;
mutate func increment();
mutate func set_value(val: uint)
}

Observe that since the method will update the counter, it is defined as mutate.

Observe also that the only the last method definition is not ended by ;.

Now regenerate the server-side bindings file using the WIDL command:

widl generate counter.widl server rust

The updated bindings.rs should include the new method set_value, in the Counter trait, and its skeleton.

bindings.rs
use serde::{Deserialize, Serialize};
use weil_macros::{constructor, mutate, query, smart_contract, WeilType};


pub trait Counter {
fn new() -> Result<Self, String>
where
Self: Sized;
async fn get_count(&self) -> usize;
async fn increment(&mut self);
async fn set_value(&mut self, val: usize);
}

#[derive(Serialize, Deserialize, WeilType)]
pub struct CounterContractState {
// define your contract state here!
}

#[smart_contract]
impl Counter for CounterContractState {
#[constructor]
fn new() -> Result<Self, String>
where
Self: Sized,
{
unimplemented!();
}

#[query]
async fn get_count(&self) -> usize {
unimplemented!();
}

#[mutate]
async fn increment(&mut self) {
unimplemented!();
}

#[mutate]
async fn set_value(&mut self, val: usize) {
unimplemented!();
}
}

Next, copy the new pieces of code to the contract implementation to the corresponding locations and fill in the logic. You need to do this because the compiler only updates the skeleton, not the implementation of the Applet.

src/lib.rs
...
#[mutate]
fn set_value(&mut self, val: usize) {
self.count = val
}
...

Execute the CLI

Assuming that the Weilliptic CLI binary is in the PATH, execute the following:

WC_PATH=~/.weilliptic WC_PRIVATE_KEY=~/.weilliptic weil_cli

Execute command connect -h <sentinel-node> The following response should be seen.

{"message":"Connected successfully to <sentinel-node>.","status":"Ok"}

Deploying the Applet

To deploy the updated Counter Applet, execute the following in the CLI:

deploy --file-path /root/code/counter/target/wasm32-unknown-unknown/release/counter.wasm --widl-file /root/code/counter/counter.widl

The contract is deployed an new contract_address is returned, different from any previously deployed.

{
"batch_author":"pod-75a62520-0.weilliptic.default.svc.cluster.local-8000",
"batch_id":"21d39243c5f1abdf3b530963ba5d0209afa66df9f6dcf902583fe0f6e4eb7e3b",
"block_height":953,
"contract_address":"7b226...227d",
"creation_time":"2024-09-30T20:30:26Z",
"status":"Finalized",
"tx_idx":0,
"txn_result":"{\"Ok\":\"null\"}",
"txn_ticket":{"Ok":"7b226...227d"}
}

Run the execute command to see the current counter value

execute --name  7b226...227d --method get_count

The result should be the following

{
"batch_author":"",
"batch_id":"",
"block_height":0,
"creation_time":"",
"status":"Finalized",
"tx_idx":0,
"txn_result":"{\"Ok\":\"0\"}"
}

Let's set the value of the counter to 10 using the set_value method:

execute -n 7b226...227d --method set_value --method-args '{"val": 10}'
{
"batch_author":"pod-7bad3bac-0.weilliptic.default.svc.cluster.local-8000",
"batch_id":"f8d22d5400f5b00e6fb9d934ce20b0a64ac10eecdfbe173ef63ffbfa0ed96789",
"block_height":39486,
"creation_time":"2024-09-30T21:54:06Z",
"status":"Finalized",
"tx_idx":0,
"txn_result":"{\"Ok\":\"null\"}"
}

followed by another call to get_count

execute -n  7b226...227d --method get_count
{
"batch_author":"",
"batch_id":"",
"block_height":0,
"creation_time":"",
"status":"Finalized",
"tx_idx":0,
"txn_result":"{\"Ok\":\"10\"}"
}

Observe that this time txn_result has value 10.

Next steps

Congratulations! You have seen how to define and deploy simple Applets. Next you should understand how to define more complex Applet state and methods.