The nexus-contract-template includes a production-ready NEP-20 implementation. Clone it, set your token name and symbol, build, and deploy.
Step 1: Clone the Template
git clone https://github.com/yattacorp/nexus-contract-template
cd nexus-contract-template
Install the WASM build target if you haven’t already:
rustup target add wasm32-unknown-unknown
Step 2: Set Your Token Name and Symbol
Open src/lib.rs and find the token constants near the top:
const TOKEN_NAME: &str = "My Token";
const TOKEN_SYMBOL: &str = "MTK";
const TOKEN_DECIMALS: u8 = 18;
Change TOKEN_NAME and TOKEN_SYMBOL to your token’s values. Leave TOKEN_DECIMALS at 18 unless you have a specific reason to change it.
You do not need to write the NEP-20 logic yourself. The template already implements transfer, approve, transferFrom, balanceOf, allowance, mint, and all standard events.
Step 3: Build
cargo build --target wasm32-unknown-unknown --release
Output: target/wasm32-unknown-unknown/release/my_nexus_contract.wasm
Step 4: Test Locally
The template includes tests for transfer, approval, and minting. All tests run against a local TestEnv — no network required.
Step 5: Deploy with TypeScript
Install the SDK:
npm install @yattacorp/nexus-sdk
Create a deploy script (deploy.ts):
import { NexusClient, Wallet } from '@yattacorp/nexus-sdk';
import { readFileSync } from 'fs';
const wallet = Wallet.fromMnemonic(process.env.MNEMONIC!, 'mainnet', undefined, 'zcash');
const client = new NexusClient(
{ rpcUrl: 'https://api.yattacorp.xyz', network: 'mainnet', chain: 'zcash' },
wallet
);
// Deploy the WASM binary
const wasm = readFileSync(
'./target/wasm32-unknown-unknown/release/my_nexus_contract.wasm'
);
const { contractId } = await client.deployContract(wasm);
console.log('Token deployed at:', contractId);
// Initialize — sets name, symbol, decimals, and mints initial supply to deployer
await client.callContract(contractId, 'init_token', [
'My Token', // name
'MTK', // symbol
18, // decimals
'1000000000000000000000000', // initial supply (1,000,000 × 10^18)
]);
console.log('Token initialized');
Run it:
init_token can only be called once — it reverts if called again. Call it immediately after deployment in the same script.
Step 6: Interact with Your Token
const tokenId = contractId; // from deployment above
// Check balance (returns raw integer string)
const balance = await client.queryContract(tokenId, 'balanceOf', [wallet.getAddress()]);
console.log('Balance:', balance);
// Transfer tokens to another address
await client.callContract(tokenId, 'transfer', [
recipientAddress,
'1000000000000000000', // 1 token (18 decimals)
]);
// Approve a spender
await client.callContract(tokenId, 'approve', [
spenderAddress,
'5000000000000000000', // 5 tokens
]);
// Query total supply
const supply = await client.queryContract(tokenId, 'totalSupply', []);
console.log('Total supply:', supply);
NEP-20 Function Reference
| Function | Args | Description |
|---|
init_token | name, symbol, decimals, supply | Initialize token (once) |
transfer | to, amount | Transfer to address |
approve | spender, amount | Approve spender |
transferFrom | from, to, amount | Spend approved tokens |
balanceOf | address | Query balance |
allowance | owner, spender | Query allowance |
totalSupply | — | Total supply |
name | — | Token name |
symbol | — | Token symbol |
decimals | — | Decimal places |
mint | to, amount | Mint new tokens (owner only) |