Skip to main content
The recommended starting point is the nexus-contract-template — a pre-configured Cargo workspace with the NEXUS SDK vendored locally, a cargo xtask build pipeline, and a full test harness already set up.

Step 1: Clone the Template

git clone https://github.com/yattacorp/nexus-contract-template
cd nexus-contract-template
The template includes:
  • Pre-vendored nexus-sdk (contract + testing modes)
  • cargo xtask build pipeline that patches WASM memory exports
  • Example contracts: counter, NEP-20 token, AMM
  • TestEnv test harness for unit testing without a live node

Step 2: Write Your Contract

Edit src/lib.rs:
#![no_std]
extern crate alloc;

use nexus_sdk::contract_api::{ez::prelude::*, ez::ret};

// State variables — persistent between calls
static INITIALIZED: Mapping<&[u8], bool> = Mapping::new(b"init");
static OWNER: Mapping<&[u8], Address> = Mapping::new(b"owner");

nexus_fn! {
    fn init() {
        let sender = Blockchain::msg.sender();
        OWNER.set(&b"val".as_slice(), sender);
        INITIALIZED.set(&b"val".as_slice(), true);
        ret::u32(1)
    }
}

nexus_fn! {
    fn greet() {
        ret::string("Hello, NEXUS!")
    }
}

Step 3: Build

cargo build --target wasm32-unknown-unknown --release
# Output: target/wasm32-unknown-unknown/release/my_nexus_contract.wasm

Step 4: Test Locally

// contract-tests/src/lib.rs
use nexus_sdk::testing::{TestEnv, accounts};

const WASM: &[u8] = include_bytes!(
    "../../target/wasm32-unknown-unknown/release/my_nexus_contract.wasm"
);

#[test]
fn test_greet() {
    let mut env = TestEnv::new();
    let contract = env.deploy(WASM).expect("deploy failed");

    env.set_caller(accounts::ALICE);
    let result = env.call(&contract, "greet", &[]).unwrap();
    result.assert_success();
}
# Build WASM first, then run tests
cargo build --target wasm32-unknown-unknown --release && cargo test

Step 5: Deploy to NEXUS

import { NexusClient, Wallet } from '@yattacorp/nexus-sdk';
import { readFileSync } from 'fs';

// Wallet must be mnemonic-based — required for vault creation and renewal key derivation
const wallet = Wallet.fromMnemonic(
  process.env.MNEMONIC!,
  'mainnet',    // 'mainnet' | 'regtest'
  undefined,    // use default BIP-32 path
  'zcash'
);

const client = new NexusClient(
  { rpcUrl: 'https://api.yattacorp.xyz', network: 'mainnet', chain: 'zcash' },
  wallet
);

const wasm = readFileSync(
  './target/wasm32-unknown-unknown/release/my_nexus_contract.wasm'
);

// Returns: { contractId, txHash, gasUsed, blockHeight }
const { contractId } = await client.deployContract(wasm);
console.log('Deployed at:', contractId);

Step 6: Call It

// State-changing call — mines on-chain, returns { success, txHash, result, gasUsed }
const result = await client.callContract(contractId, 'greet', []);
console.log('Result:', result.result);

// Stealth call — same execution, caller identity hidden on-chain
const result = await client.stealthCallContract(contractId, 'greet', []);

// Read-only query — no gas, no transaction
const value = await client.queryContract(contractId, 'greet', []);

Next Steps