Skip to content

Repository files navigation

ceps-rust-ts-client

One Rust client for Casper CEP-18, CEP-78, CEP-85, and CEP-95, with a ceps-client-cli, ceps-rust-ts-client-mcp, and WASM packs so the same client can run from shell, agents, Node, or the browser.

It replaces the separate TypeScript client-js packages that lived next to each CEP contract. Instead of per-CEP JS clients, you use one library: CEP18Client / CEP78Client / CEP85Client / CEP95Client, on top of casper-rust-wasm-sdk.

CEP-18 client-js  ─┐
CEP-78 client-js  ─┼─→  ceps-client (Rust)  +  ceps-client-cli  +  ceps-rust-ts-client-mcp  +  ceps-client-wasm
CEP-85 client-js  ─┤
CEP-95 JS client  ─┘

What you get

Piece Name Role In-tree path
Rust library ceps‑client CEP API for native Rust apps ceps-client/
CLI ceps‑client‑cli Status and common queries from the shell ceps-client-cli/
MCP server ceps-rust-ts-client-mcp Full CEP agent tools (stdio / HTTP :6790) mcp/
Client JS packs ceps‑client‑wasm Same CEP classes for Node and browsers (replaces per-CEP client-js) ceps-client-wasm/pkg / pkg-nodejs
Demo contract WASMs ceps‑contracts On-chain bytecode for install (demo tips) tests/wasm/{cep18,cep78,cep85,cep95}/

Release downloads use the same names: ceps-client-cli-*-linux-x86_64, ceps-rust-ts-client-mcp-*-linux-x86_64, ceps-client-wasm-*.tgz, and ceps-contracts-*.tgz. The library / CLI / MCP / JS packs are this client; ceps-contracts is sample contract bytecode, not the JS library.

What you can do

CEP Standard Typical flow
18 Fungible token install → bind hash → name / balance_oftransfer / mint / burn
78 Enhanced NFT install → bind hash → mintowner_of / balance_of
85 Multi-token install → bind hash → mint / burnbalance_of(account, id)
95 NFT (Odra tip) install → bind_odra_installmintowner_of / approve

Defaults talk to local NCTL (http://127.0.0.1:11101, SSE …:18101/events, chain casper-net-1).

Usage

Needs a running node, a secret-key PEM, and on-chain contract .wasm bytes (your own build, or the demo tips via make wasm-from-ceps).

CEP-18 - fungible

install → named keys cep18_contract_hash_* / package_*
  → set_contract_hash
  → name / symbol / balance_of
  → transfer | mint | burn
use ceps_client::cep18::InstallArgs;
use ceps_client::{CEP18Client, TransactionParams, EventsMode, Verbosity};

let mut client = CEP18Client::new(
    "http://127.0.0.1:11101",
    Some("http://127.0.0.1:18101/events".into()),
    Some("casper-net-1".into()),
    Some(Verbosity::Low),
)?;

let put = client
    .install(
        &InstallArgs::new("MyToken", "MTK", 9, "1000000000")
            .with_events_mode(EventsMode::CES)
            .with_mint_and_burn(true),
        &contract_wasm_bytes,
        &TransactionParams::new(&secret_pem, "400000000000"),
    )
    .await?;
client.set_contract_hash(&contract_hash, Some(&package_hash))?;
let bal = client.balance_of("account-hash-…").await?;

Details: docs/cep18/ · example: cargo run -p ceps-client --example cep18_install

CEP-78 - NFT

install → named keys cep78_contract_hash_* / package_*
  → set_contract_hash
  → mint → owner_of / balance_of
use ceps_client::cep78::InstallArgs;
use ceps_client::{CEP78Client, TransactionParams, EventsMode78, Verbosity};

let mut client = CEP78Client::new(/* rpc, sse, chain, verbosity */)?;
client
    .install(
        &InstallArgs::new("MyNft", "NFT", 100).with_events_mode(EventsMode78::CES),
        &contract_wasm_bytes,
        &TransactionParams::new(&secret_pem, "600000000000"),
    )
    .await?;
client.set_contract_hash(&contract_hash, Some(&package_hash))?;
client
    .mint(
        "account-hash-…",
        r#"{"name":"token-1"}"#,
        None,
        &TransactionParams::new(&secret_pem, "5000000000"),
    )
    .await?;
let owner = client.owner_of(&token_id).await?;

Details: docs/cep78/ · example: cargo run -p ceps-client --example cep78_install

CEP-85 - multi-token

install → named keys cep85_contract_hash_* / package_*
  → set_contract_hash
  → mint / burn → balance_of(account, id)
use ceps_client::cep85::InstallArgs;
use ceps_client::{CEP85Client, TransactionParams, EventsMode, Verbosity};

let mut client = CEP85Client::new(/* rpc, sse, chain, verbosity */)?;
client
    .install(
        &InstallArgs::new("MyMulti", "https://example.com/{id}.json")
            .with_events_mode(EventsMode::CES)
            .with_enable_burn(true),
        &contract_wasm_bytes,
        &TransactionParams::new(&secret_pem, "550000000000"),
    )
    .await?;
client.set_contract_hash(&contract_hash, Some(&package_hash))?;
client.mint(&owner, "1", "10", None, &TransactionParams::new(&secret_pem, "5000000000")).await?;
let bal = client.balance_of(&owner, "1").await?;

Details: docs/cep85/ · example: cargo run -p ceps-client --example cep85_install

CEP-95 - NFT (Odra tip)

install (odra_cfg_package_hash_key_name) → bind_odra_install
  → name / symbol / balance_of / owner_of
  → mint | burn | transfer_from | approve*
use ceps_client::cep95::InstallArgs;
use ceps_client::{CEP95Client, TransactionParams, Verbosity};

let mut client = CEP95Client::new(/* rpc, sse, chain, verbosity */)?;
client
    .install(
        &InstallArgs::new("MyNft", "MNFT", "cep95_pkg_demo"),
        &contract_wasm_bytes,
        &TransactionParams::new(&secret_pem, "600000000000"),
    )
    .await?;
client.bind_odra_install(&installer_public_key, "cep95_pkg_demo").await?;
client.mint(&owner, "1", None, &TransactionParams::new(&secret_pem, "5000000000")).await?;
let owner_of = client.owner_of("1").await?;

Details: docs/cep95/ · example: cargo run -p ceps-client --example cep95_install

CLI

cargo run -p ceps-client-cli -- status
cargo run -p ceps-client-cli -- cep18 info
cargo run -p ceps-client-cli -- cep78 balance --contract-hash <hash> --account <account-hash-…>
cargo run -p ceps-client-cli -- cep85 balance --contract-hash <hash> --account <> --id 1
cargo run -p ceps-client-cli -- cep95 owner-of --contract-hash <hash> --token-id 1

Mutations are on the library / examples today. Flags: docs/cli.md.

Try an install end-to-end

make prepare && make build
make wasm-from-ceps          # copy demo tip contract WASMs into tests/wasm/
# NCTL running + SECRET_KEY_USER_1 set to a PEM:
cargo run -p ceps-client --example cep18_install

More setup: docs/getting-started.md.

Client JS packs (ceps-client-wasm)

ceps-client-wasm is the Rust CEP client compiled for JavaScript (the replacement for per-CEP client-js). Use it from Node or the browser for the same CEP18Client / CEP78Client / CEP85Client surface.

It is not on-chain contract bytecode (that is tests/wasm/ / ceps-contracts-*.tgz).

Target In-tree (committed) Typical use
Node ceps-client-wasm/pkg-nodejs/ Backend / scripts / Vitest
Web ceps-client-wasm/pkg/ Bundled frontends

Rebuild locally with make pack (or make nodejs / make web). Details: docs/wasm-ts.md · docs/releases.md.

Or fetch a published pack (no local wasm-pack):

TAG=v1.0.0   # or dev-preview
LABEL=${TAG#v}
curl -fsSL -o ceps-client-wasm-nodejs.tgz \
  "https://github.com/Interchouette-ITC/ceps-rust-ts-client/releases/download/${TAG}/ceps-client-wasm-nodejs-${LABEL}.tgz"
mkdir -p ceps-client-wasm && tar -xzf ceps-client-wasm-nodejs.tgz -C ceps-client-wasm
# -> ceps-client-wasm/pkg-nodejs/
import { CEP18Client } from "ceps-client-wasm"; // file:./ceps-client-wasm/pkg-nodejs after unpack

const client = new CEP18Client(
  "http://127.0.0.1:11101",
  "http://127.0.0.1:18101/events",
  "casper-net-1",
  0,
);
client.setContractHash(contractHash, packageHash);
const name = await client.name();
const bal = await client.balanceOf("account-hash-…");

Install from JS takes contract bytes as Uint8Array and returns JSON { transactionHash, hasExecutionResult }. Bound methods today are a subset of the Rust API (see docs/wasm-ts.md); full parity is on ceps-client.

Contract WASMs (demos)

This client is not a contract repo. You pass on-chain .wasm into install.

In-tree: the last staged demo tip builds ship under tests/wasm/{cep18,cep78,cep85,cep95}/ (same idea as committing pkg / pkg-nodejs). Load with ceps_client::wasm::load("cep18") under CEPS_WASM_ROOT (default tests/wasm), or refresh with make wasm-from-ceps.

Or download the release bundle (no tip checkout / no contract build):

TAG=v1.0.0
LABEL=${TAG#v}
curl -fsSL -o ceps-contracts.tgz \
  "https://github.com/Interchouette-ITC/ceps-rust-ts-client/releases/download/${TAG}/ceps-contracts-${LABEL}.tgz"
mkdir -p tests/wasm && tar -xzf ceps-contracts.tgz -C tests/wasm

Tips are short-lived entity-era builds for demos/CI, not a claim of "the" upstream CEP tip forever. Sources:

CEP Demo tip repo Branch What you get
18 Interchouette-ITC/cep-18 ceps-client-test Fungible contract WASM
78 Interchouette-ITC/cep-78-enhanced-nft ceps-client-test NFT + session WASMs
85 Interchouette-ITC/cep-85 ceps-client-test Multi-token WASM
# after checking out those tips and building contracts there:
make wasm-from-ceps   # → tests/wasm/{cep18,cep78,cep85}/

Override checkout roots with CEP18_PRODUCT / CEP78_PRODUCT / CEP85_PRODUCT. Pins and SHAs: docs/contributing.md. All release downloads: docs/releases.md.

Documentation

Doc Description
Getting started Build, NCTL defaults, first run
Architecture How lib / CLI / WASM sit on the SDK
docs/cep18/ · cep78/ · cep85/ Per-CEP guides
CLI · WASM / TS Surfaces
Testing · CI / CD · Releases · Docker Verify and ship
Contributing · SDK Tips, pins, upgrades
SECURITY.md Keys and reporting
make doc rustdoc → docs/api-rust/

Docker

make release-cli-bin && make docker-build IMAGE_TAG=local
docker run --rm ceps-rust-ts-client:local --help
docker pull interchouette/ceps-rust-ts-client:dev

See docs/docker.md.

License / security

GPL-3.0. See LICENSE and docs/SECURITY.md.

About

Unified Rust client for Casper CEP-18, CEP-78, CEP-85, and CEP-95 (library, CLI, and WASM).

Resources

Contributing

Security policy

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages