Skip to content

SDK & Client Integration

The sdk crate (packages/sdk) provides Rust types and an optional HTTP client for interacting with Wasichain nodes.

Installation

[dependencies]
sdk = { path = "../chain/packages/sdk" }

# Enable the HTTP client
sdk = { path = "../chain/packages/sdk", features = ["client"] }

# Optional: enable the polling helper that uses tokio::time::sleep
sdk = { path = "../chain/packages/sdk", features = ["client", "wait-tokio"] }

Feature flags

Feature Dependencies What it enables
(default) none Re-exported types only (addresses, transactions, signing, receipts)
client reqwest ChainClient for HTTP communication with a node
wait-tokio tokio wait_for_code() polling helper

The SDK client does not need a direct tokio dependency just to compile. You still need an async runtime in the application that drives the HTTP client.

Re-exported types

The SDK re-exports core types so consumers do not need to depend on the types crate directly:

  • Address, Hash, format_hash, parse_hash, sha256, derive_contract_address
  • Tx, SignedTx
  • ExecutionReceipt, CallTrace, Event
  • Limits
  • generate_keypair, load_signing_key, sign_tx, verify_tx_signature
  • SubMessage, SubMessageResult, ReplyOn
  • CodeRecord, CodeStatus, ContractRecord
  • DEFAULT_VM_VERSION

ChainClient

When the client feature is enabled, ChainClient provides typed methods for all RPC endpoints:

use sdk::ChainClient;

let client = ChainClient::new("http://<host>:8080");

// Query node status
let status = client.status().await?;
println!("height: {}, epoch: {}", status.height, status.epoch);

// Check account balance and nonce
let acct = client.account("<ADDRESS>").await?;

// Submit a signed transaction
let tx_resp = client.submit_tx(&signed_tx).await?;

// Look up a transaction receipt
let receipt = client.get_tx(&tx_resp.tx_hash).await?;

// Query code status
let code = client.code_by_hash("<HASH>").await?;

// Query a contract
let result = client.query_contract("<CONTRACT_ADDR>", msg_bytes).await?;

// Get validator set
let vset = client.validator_set().await?;

// Get block transactions
let block = client.block_txs(42).await?;

If you enable wait-tokio, you also get:

let code = client
    .wait_for_code("<HASH>", "activated", Duration::from_secs(2))
    .await?;

Signing transactions

use sdk::{generate_keypair, sign_tx, Tx};

let (signing_key, address) = generate_keypair();

let tx = Tx::Transfer { to: recipient, amount: 1000 };
let signed = sign_tx(tx, nonce, &signing_key);

Deriving contract addresses

Contract addresses are deterministic, derived from the creator address, code ID, and a salt:

use sdk::{derive_contract_address, sha256};

let salt = sha256(b"my-contract-label");
let addr = derive_contract_address(&creator, code_id, &salt);

Why code_id instead of hashing the Wasm again?

  • code_id is the chain-local handle for an activated code record
  • that record includes the raw code_hash
  • duplicate code hashes are rejected, so one code_id corresponds to one unique uploaded binary

The salt is there so the same creator can instantiate the same code more than once without address collisions.