Tenzro Testnet is live —request testnet TNZO
← Back to Tutorials
SDKBeginner

TypeScript SDK Quickstart

Get up and running with the Tenzro TypeScript SDK in under 5 minutes. You will connect to the testnet, create a wallet, check your balance, send TNZO, register a decentralized identity, list available AI models, and run inference -- all from TypeScript. Works in Node.js and the browser.

Prerequisites

  • Node.js 18+ or Bun 1.0+
  • Internet connection (for testnet RPC calls)

Estimated time: 5 minutes

Step 1: Create a New Project

Create a new project and install the SDK:

mkdir my-tenzro-app && cd my-tenzro-app
npm init -y
npm install tenzro-sdk
npm install -D typescript tsx @types/node
npx tsc --init

Or with Bun:

mkdir my-tenzro-app && cd my-tenzro-app
bun init
bun add tenzro-sdk

Step 2: Connect to Testnet

Create src/index.ts and connect to the Tenzro testnet. The SDK exports a pre-configured TESTNET_CONFIG:

import { TenzroClient, TESTNET_CONFIG } from "tenzro-sdk";

async function main() {
  // Connect to testnet
  const client = new TenzroClient(TESTNET_CONFIG);

  // Verify connection
  const info = await client.nodeInfo();
  console.log("Connected to Tenzro Network");
  console.log("  Chain ID:", info.chain_id);
  console.log("  Block height:", info.block_height);
  console.log("  Peers:", info.peer_count);
}

main().catch(console.error);

Run it:

npx tsx src/index.ts

Expected output:

Connected to Tenzro Network
  Chain ID: 1337
  Block height: 482910
  Peers: 5

Custom Endpoints

To connect to a local node, create a custom config: { endpoint: "http://localhost:8545", timeout: 30000 }. The TESTNET_CONFIG points to https://rpc.tenzro.network.

Step 3: Create a Wallet

Create a new wallet using the WalletClient:

import { TenzroClient, TESTNET_CONFIG } from "tenzro-sdk";

async function main() {
  const client = new TenzroClient(TESTNET_CONFIG);

  // Create a new Ed25519 wallet
  const walletInfo = await client.wallet.createWallet();
  console.log("Wallet created!");
  console.log("  Address:", walletInfo.address);
}

main().catch(console.error);

Step 4: Fund from Faucet

Request 100 testnet TNZO tokens from the faucet (24-hour cooldown per address):

// Request testnet tokens
const faucet = await client.requestFaucet(walletInfo.address);
console.log("Faucet:", faucet.amount, "TNZO received");
console.log("  Tx hash:", faucet.tx_hash);

Step 5: Check Balance

Query the wallet balance:

// Get TNZO balance (returns bigint in wei)
const balance = await client.wallet.getBalance(walletInfo.address);
console.log("Balance:", balance.toString(), "wei");

// Convert to human-readable TNZO (18 decimals)
const tnzo = Number(balance) / 1e18;
console.log("Balance:", tnzo, "TNZO");

Step 6: Send TNZO

Transfer TNZO to another address:

Every Tenzro transaction is hybrid post-quantum signed: a classical Ed25519 signature and an ML-DSA-65 (FIPS 204) signature, both verified synchronously by the node against the canonical Transaction::hash()preimage (which commits to the wallet's ML-DSA-65 public key). An invalid or missing signature on either leg returns JSON-RPC error -32003.

The recommended flow is client.wallet.signAndSend(...), a thin wrapper over tenzro_signAndSendTransaction. Auth is mandatory — the SDK attaches your DPoP-bound bearer JWT, the node identifies the signing wallet, signs both legs, verifies them, and submits to the mempool atomically. Private keys never travel over the wire.

// Send 1 TNZO via atomic server-side hybrid sign + submit
const txHash = await client.wallet.signAndSend({
  from: walletInfo.address,
  to: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb4",
  value: 1_000_000_000_000_000_000n, // 1 TNZO in wei
});
console.log("Transaction sent:", txHash);

// Check updated balance
const newBalance = await client.wallet.getBalance(walletInfo.address);
console.log("New balance:", Number(newBalance) / 1e18, "TNZO");

Offline / pre-signed submission

For batched or air-gapped flows, call tenzro_signTransaction to obtain{signature, public_key, pq_signature, pq_public_key, timestamp, tx_hash}, then resubmit later via eth_sendRawTransaction with all six fields intact. Missing any field returns -32003.

Step 7: Register an Identity

Register a TDIP identity using the IdentityClient:

// Register a human identity
const idResult = await client.identity.registerHuman("Alice");
console.log("Identity registered!");
console.log("  DID:", idResult.did);
console.log("  Status:", idResult.status);

// Resolve the identity
const resolved = await client.identity.resolve(idResult.did);
console.log("  Type:", resolved.identity_type);
console.log("  KYC Tier:", resolved.kyc_tier);

Expected output:

Identity registered!
  DID: did:tenzro:human:550e8400-e29b-41d4-a716-446655440001
  Status: active
  Type: human
  KYC Tier: 0

Step 8: List Models and Run Inference

Discover available AI models and send an inference request:

// List available models
const models = await client.inference.listModels();
console.log("Available models:", models.length);
for (const model of models) {
  console.log(`  ${model.model_id} - ${model.name} (${model.status})`);
}

// Run inference
const response = await client.inference.request(
  "gemma3-270m",                         // model ID
  "Explain blockchain in one sentence.", // prompt
  100,                                   // max tokens
);
console.log("Response:", response.output);
console.log("Tokens:", response.tokens_used);
console.log("Cost:", response.cost, "TNZO");

Step 9: The AppClient Pattern

For building user-facing applications, use AppClient instead of TenzroClient. The AppClient wraps a master wallet and provides a paymaster pattern where you sponsor gas for your users:

import { AppClient } from "tenzro-sdk";

async function main() {
  // Create an AppClient with your master wallet
  const app = await AppClient.new(
    "https://rpc.tenzro.network",
    process.env.MASTER_PRIVATE_KEY!,
  );

  // Create a user wallet (funded from master)
  const user = await app.createUserWallet(
    "alice",
    100_000_000_000_000_000n, // 0.1 TNZO initial funding
  );
  console.log("User wallet:", user.address);

  // Set spending limits
  await app.setUserLimits(
    user.address,
    5_000_000_000_000_000_000n,  // 5 TNZO/day
    1_000_000_000_000_000_000n,  // 1 TNZO/tx
  );

  // Sponsor an inference request (gas paid by master wallet)
  const result = await app.sponsorInference(
    user.address,
    "gemma3-270m",
    "Hello from my app!",
  );
  console.log("Output:", result.output);
  console.log("Cost:", result.cost, "TNZO");

  // Check usage stats
  const stats = await app.getUsageStats();
  console.log("Total gas spent:", stats.totalGasSpent.toString());
  console.log("Total transactions:", stats.transactionCount);
}

main().catch(console.error);

TenzroClient vs AppClient

TenzroClient is for direct interaction -- each user manages their own wallet and gas. AppClient is for developer-funded applications -- you control a master wallet and sponsor transactions on behalf of your users. AppClient is ideal for building web apps, mobile apps, and SaaS products where you do not want users to manage crypto.

Complete Example

Here is the full quickstart in a single file:

import { TenzroClient, TESTNET_CONFIG } from "tenzro-sdk";

async function main() {
  // 1. Connect
  const client = new TenzroClient(TESTNET_CONFIG);
  const info = await client.nodeInfo();
  console.log("Connected (chain", info.chain_id + ")");

  // 2. Create wallet
  const wallet = await client.wallet.createWallet();
  console.log("Wallet:", wallet.address);

  // 3. Fund from faucet
  const faucet = await client.requestFaucet(wallet.address);
  console.log("Funded:", faucet.amount, "TNZO");

  // 4. Check balance
  const balance = await client.wallet.getBalance(wallet.address);
  console.log("Balance:", Number(balance) / 1e18, "TNZO");

  // 5. Register identity
  const id = await client.identity.registerHuman("Alice");
  console.log("DID:", id.did);

  // 6. List models
  const models = await client.inference.listModels();
  console.log("Models:", models.length);

  // 7. Run inference
  const response = await client.inference.request(
    "gemma3-270m",
    "What is Tenzro Network?",
    100,
  );
  console.log("Response:", response.output);
}

main().catch(console.error);

Sub-Client Reference

The TenzroClient exposes these sub-clients as properties:

PropertyTypePurpose
client.walletWalletClientCreate wallets, balances, send transactions
client.inferenceInferenceClientList models, run inference
client.identityIdentityClientRegister/resolve TDIP identities
client.paymentPaymentClientMPP, x402, native payment flows
client.agentAgentClientRegister agents, messaging, task delegation
client.governanceGovernanceClientProposals, voting, voting power
client.settlementSettlementClientEscrow, micropayments
client.tokenTokenClientCreate tokens, cross-VM transfers
client.stakingStakingClientStake/unstake, register as provider
client.bridgeBridgeClientCross-chain bridges
client.cryptoCryptoClientSign, verify, encrypt, key exchange
client.streamingStreamingClientSSE streaming, real-time events
client.cantonCantonClientCanton/DAML enterprise integration
client.teeTeeClientTEE attestation, enclave operations
client.zkZkClientZK proof generation and verification
client.contractContractClientDeploy and call smart contracts

What You Learned

Next Steps

Build More with Tenzro

Ready to build something more complex? Explore the full SDK documentation and examples.