Client SDK
Once the smart contract is deployed on the WeilChain, developers would be interested in interacting with it and build exciting applications on top of it. This is realized through the Weilliptic Client SDK
. We provide client SDK in TypeScript, Rust and Golang. Let's again take example of counter widl interface:
interface Counter {
query func get_count() -> uint;
mutate func increment()
}
The steps are slightly different depending on the language you are using, so make sure to chose the right language now.
- Rust
- Go
- AssemblyScript
- CPP
You have chosen Rust!
You have chosen Go!
You have chosen AssemblyScript!
You have chosen C++!
Now to generate client bindings from widl, use following command:
- Rust
- Go
- TypeScript
widl generate counter.widl client rust
widl generate counter.widl client go
widl generate counter.widl client tsc
which will generate a bindings file
- Rust
- Go
- TypeScript
use serde::{Deserialize, Serialize};
use w_wasmutils::errors::WeilError;
use weil_wallet::{contract::ContractId, wallet::Wallet, WeilClient, WeilContractClient};
struct CounterClient {
client: WeilContractClient,
}
impl CounterClient {
pub fn new(contract_id: ContractId, wallet: Wallet) -> Result<Self, anyhow::Error> {
Ok(CounterClient {
client: WeilClient::new(wallet)?.to_contract_client(contract_id),
})
}
pub async fn get_count(&self) -> Result<u32, anyhow::Error> {
#[derive(Serialize)]
struct Args {
}
let args = Args { };
let resp = self.client.execute("get_count".to_string(), serde_json::to_string(&args).unwrap()).await?;
let txn_result = serde_json::from_str::<Result<String, WeilError>>(&resp.txn_result)?;
let result = txn_result?;
let result = serde_json::from_str::<u32>(&result)?;
Ok(result)
}
pub async fn increment(&self) -> Result<(), anyhow::Error> {
#[derive(Serialize)]
struct Args {
}
let args = Args { };
let resp = self.client.execute("increment".to_string(), serde_json::to_string(&args).unwrap()).await?;
let txn_result = serde_json::from_str::<Result<String, WeilError>>(&resp.txn_result)?;
let result = txn_result?;
let result = serde_json::from_str::<()>(&result)?;
Ok(result)
}
}
package counterContract
import (
"encoding/json"
"fmt"
"errors"
"github.com/weilliptic-inc/contract-sdk/go/weil_wallet/client"
"github.com/weilliptic-inc/contract-sdk/go/weil_wallet/wallet"
"github.com/weilliptic-inc/contract-sdk/go/weil_go/types"
)
type CounterClient struct {
client *client.WeilContractClient
}
func NewCounterClient(contractId string, wallet *wallet.Wallet) *CounterClient {
weilClient := client.NewWeilClient(wallet)
weilContractClient := weilClient.ToContractClient(contractId)
return &CounterClient{
client: weilContractClient,
}
}
func (cli *CounterClient) GetCount() (*uint32, error) {
type Arg struct {
}
args := Arg {
}
argsBytes, err := json.Marshal(args)
if err != nil {
return nil, err
}
txnResult, err := cli.client.Execute("get_count", string(argsBytes))
if err != nil {
return nil, err
}
var result types.Result[string, string]
err = json.Unmarshal([]byte(txnResult.TxnResult), &result)
if err != nil {
err = errors.New(err.Error() + txnResult.TxnResult)
return nil, err
}
if result.IsErrResult() {
err = errors.New(*result.TryErrResult())
return nil, err
}
resultStr := result.TryOkResult()
var resultVal uint32
err = json.Unmarshal([]byte(*resultStr), &resultVal)
if err != nil {
return nil, err
}
return &resultVal, nil
}
func (cli *CounterClient) Increment() error {
type Arg struct {
}
args := Arg {
}
argsBytes, err := json.Marshal(args)
if err != nil {
return err
}
txnResult, err := cli.client.Execute("increment", string(argsBytes))
if err != nil {
return err
}
var result types.Result[string, string]
err = json.Unmarshal([]byte(txnResult.TxnResult), &result)
if err != nil {
err = errors.New(err.Error() + txnResult.TxnResult)
return err
}
if result.IsErrResult() {
err = errors.New(*result.TryErrResult())
return err
}
return nil
}
import {
WeilWallet,
Schema,
Contract,
ContractFactory,
parseSchema,
parseExecutionResult,
} from '@weilliptic/weil-sdk';
export const Counter = ((wallet: WeilWallet, contractAddress: string) => ({
get_count: async (): Promise<number> => {
const args = {}
const result = await wallet.contracts.execute(
contractAddress,
"get_count",
args
);
return parseExecutionResult(result, Schema.u32);
},
increment: async (): Promise<void> => {
const args = {}
const result = await wallet.contracts.execute(
contractAddress,
"increment",
args
);
parseExecutionResult(result, Schema.void);
return;
},
} satisfies Contract)) satisfies ContractFactory;
This CounterClient
can be used to interact with the Counter
smart contract with the provided ContractId
.
- Rust
- Go
- TypeScript
So a very simple main program in rust would look like:
#[tokio::main]
async fn main() {
// put path of the private key here!
let private_key = PrivateKey::from_file("/root/.weilliptic/private_key.wc").unwrap();
let wallet = Wallet::new(private_key).unwrap();
// put your contract id here!
let contract_id = "0000000279b490f8823ec1ce7e3c6ff2600500afa0e58eb59a1572afd25d0d4d16eb7512"
.parse::<ContractId>()
.unwrap();
let client = CounterClient::new(contract_id, wallet).unwrap();
let count = client.get_count().await.unwrap();
println!("count: {:?}", count);
client.increment().await.unwrap();
let count = client.get_count().await.unwrap();
println!("count: {:?}", count);
}
So a very simple main program in go would look like:
package main
import (
"<counter-package-name>/counterContract"
"fmt"
"github.com/weilliptic-inc/contract-sdk/go/weil_wallet/wallet"
)
func main() {
// put path to the private key here!
wallet, _ := wallet.NewWallet("/root/.weilliptic/private_key.wc")
// put your contract id here!
contractId := "00000002b14df03428e10506946ae3e2a86217954cfc204e80f80290a72f978838e1cd4e"
countercli := NewCounterClient(contractId, wallet)
v, e := countercli.GetCount()
fmt.Println(*v, e)
e1 := countercli.Increment()
fmt.Println(e1)
v1, e2 := countercli.GetCount()
fmt.Println(*v1, e2)
}
This Counter
object factory can be used to interact with the Counter
smart contract with the provided contractAddress
. So a very simple main program in Typescript would look like:
// put your private key here!
import { Counter } from './bindings.ts';
import { WeilWallet } from '@weilliptic/weil-wallet-sdk';
const privateKey = '0000000000000000000000000000000000000000000000000000000000000000';
const wallet = new WeilWallet({
privateKey,
sentinelEndpoint: 'http://sentinel:8000',
});
// put counter's contract address here!
const contractAddress = '000000000000000000000000000000000000000000000000000000000000000000000000'
const run = async () => {
const counter = Counter(wallet, contractAddress);
console.log(`Counter is at ${await counter.get_count()}`);
console.log('Incrementing it');
await counter.increment();
console.log(`Counter is now at ${await counter.get_count()}`);
}
run()
Hence client SDK is a great way to programmatically interact with the smart contract and build cool decentralized application in your favourite language!