TypeScript SDK For Smart Contracts
This page explains the TypeScript SDK helpers for smart contract publishing, calling, inspection, and package automation. It focuses on what the SDK builds and submits.
For the deployment workflow and release evidence, use:
SDK Boundary
The SDK imports protocol definitions from:
src/protocol/public-api.tsThat file re-exports transaction types, payload schemas, envelope types, hash helpers, and signing helpers from the core chain modules. This keeps the SDK aligned with the executor and avoids duplicate payload definitions.
Helper Map
| Goal | SDK helper | Transaction or API |
|---|---|---|
| Hash WASM bytes | hashContractCode(...) | local helper |
| Hash a manifest | hashContractManifest(...) | local helper |
| Build a manifest object | contractManifest(...), contractMethod(...) | local helper |
| Deploy code | client.contracts.deployCode(...) | transaction DEPLOY_CONTRACT_CODE |
| Instantiate a contract | client.contracts.instantiate(...) | transaction INSTANTIATE_CONTRACT |
| Publish loose WASM and manifest | client.contracts.publish(...) | transactions DEPLOY_CONTRACT_CODE and INSTANTIATE_CONTRACT |
| Grant contract bucket access | client.contracts.grantBucketAccess(...) | transaction GRANT_CONTRACT_BUCKET_ACCESS |
| Call a method | client.contracts.call(...) | transaction CALL_CONTRACT |
| Deactivate a contract | client.contracts.deactivate(...) | transaction DEACTIVATE_CONTRACT |
| Load a package from disk | loadContractPackageFromDirectory(...) | Node.js filesystem helper |
| Publish a package | client.contracts.publishPackage(...) | transactions DEPLOY_CONTRACT_CODE and INSTANTIATE_CONTRACT |
| Register a package | client.contracts.registerPackage(...) | transaction REGISTER_CONTRACT_PACKAGE |
| Update package status | client.transactions.updateContractPackageStatus(...) | transaction UPDATE_CONTRACT_PACKAGE_STATUS |
| Read ABI | client.contracts.abi(...) | GET /contracts/{contractId}/abi |
| Read call result | client.contracts.callResult(...) | receipt API |
| Query events | client.contracts.events(...) | event query API |
| Inspect metrics | client.observability.contracts(...) | operator API |
Build A Manifest
Use contractManifest(...) when TypeScript code or deployment automation needs to build the manifest object before hashing or publishing.
import { contractManifest } from "@nooschain/client";
const manifest = contractManifest({
name: "report-store",
version: "0.1.0",
runtime: "wasm-assemblyscript-v1",
methods: {
saveReport: {
entrypoint: "saveReport",
maxFuel: 250000,
invoke: {
allow: [{ principalType: "organization", principalId: "org-noos" }],
},
buckets: [],
abi: {
description: "Store a report and emit report.saved.",
input: {
type: "object",
properties: {
reportId: { type: "string" },
status: {
type: "string",
enum: ["draft", "submitted", "approved", "rejected"],
},
score: { type: "integer" },
},
required: ["reportId", "status", "score"],
},
output: {
type: "object",
properties: { ok: { type: "boolean" } },
required: ["ok"],
},
events: [
{
topic: "report.saved",
schema: {
type: "object",
properties: {
reportId: { type: "string" },
status: { type: "string" },
},
required: ["reportId", "status"],
},
},
],
},
},
},
});The manifest hash changes when method ABI, authorization, bucket declarations, calls, migrations, runtime, or other canonical manifest fields change. For field-by-field manifest guidance, see Manifests.
Publish Loose WASM And Manifest
client.contracts.publish(...) is a convenience helper for deployments where automation already has WASM bytes and a manifest object.
import {
NooschainClient,
PemTransactionSigner,
contractManifest,
} from "@nooschain/client";
const client = new NooschainClient({ baseUrl: "http://127.0.0.1:3000" });
const signer = new PemTransactionSigner({ publicKey, privateKeyPem });
const publish = await client.contracts.publish({
signer,
nonce: "auto",
submit: true,
code: wasmBytes,
contractId: "contract-report-store",
manifest,
ownerUserId: "user-admin",
organizationId: "org-noos",
});
console.log(publish.deploy.transaction.hash);
console.log(publish.instantiate.transaction.hash);The helper builds transaction DEPLOY_CONTRACT_CODE and transaction INSTANTIATE_CONTRACT. With submit: true, it submits both transactions. With submit: false, it returns the signed transactions so callers can review, store, or submit them later.
Use the lower-level helpers when you need separate control over each step:
client.contracts.deployCode(...);client.contracts.instantiate(...);client.transactions.deployContractCode(...);client.transactions.instantiateContract(...).
For the recommended release workflow, see Publishing.
Publish A Contract Package
Use packages when you want repeatable artifacts instead of loose WASM and manifest values. The SDK can load, validate, hash, and publish a package.
import { loadContractPackageFromDirectory } from "@nooschain/client";
const contractPackage = await loadContractPackageFromDirectory(
"apps/noos-contract-sdk-as/examples/typed-report-contract/package",
);
const publish = await client.contracts.publishPackage({
signer,
nonce: "auto",
submit: true,
package: contractPackage,
contractId: "contract-typed-report",
ownerUserId: "user-admin",
organizationId: "org-noos",
bucketAccess: [
{
bucketId: "reports",
permissions: ["bucket:read_metadata"],
},
],
});loadContractPackageFromDirectory(...) is available from the Node.js entrypoint because it reads files from disk. Browser clients can use shared descriptor validation helpers, but they cannot load package directories from local paths.
publishPackage(...) builds transaction DEPLOY_CONTRACT_CODE and transaction INSTANTIATE_CONTRACT. If the package includes provenance/signatures.json, the helper can attach package provenance to the instantiate payload.
The package, descriptor, signature, and policy rules are documented in Packages And Provenance and Package Provenance.
Local Signature Preflight
publishPackage(...) accepts signaturePolicy as a local SDK preflight. It is useful when a tool wants to fail before submission if a loaded package is not signed by an expected actor.
await client.contracts.publishPackage({
signer,
nonce: "auto",
submit: true,
package: contractPackage,
contractId: "contract-typed-report",
ownerUserId: "user-admin",
organizationId: "org-noos",
signaturePolicy: {
requireSignature: true,
allowedSignerTypes: ["user"],
allowedSignerIds: ["user-admin"],
},
});This SDK preflight is not the network authority. Validators enforce the active chain provenance policy during transaction INSTANTIATE_CONTRACT. For policy setup and deterministic rejection behavior, see Package Provenance.
Call A Contract
Use client.contracts.call(...) to build transaction CALL_CONTRACT.
const call = await client.contracts.call({
signer,
nonce: "auto",
contractId: "contract-report-store",
method: "saveReport",
args: {
reportId: "report-001",
status: "submitted",
score: 97,
},
});
await client.transactions.submit(call.transaction);The SDK signs the transaction envelope. The contract runtime executes the call only after the transaction is included and validated by the chain.
Read ABI
Contracts can expose ABI metadata through their manifest. Fetch deployed ABI with:
const abi = await client.contracts.abi("contract-report-store");
const saveReport = abi.methods.saveReport;
console.log(saveReport.input);
console.log(saveReport.events.map((event) => event.topic));The HTTP endpoint is:
GET /contracts/{contractId}/abiLegacy methods without ABI metadata return input: null, output: null, and events: [].
Read Call Results
Successful contract calls can store one structured JSON return value as a deterministic execution receipt. Fetch it after transaction CALL_CONTRACT is included and executed:
const result = await client.contracts.callResult(call.transaction.hash);
console.log(result.returnValue);
console.log(result.fuelUsed);The same receipt is also available as transaction.contractResult in client.transactions.get(hash) after execution.
Query Contract Events
Use event queries for activity feeds, indexers, and transaction diagnostics.
const events = await client.contracts.events({
contractId: "contract-report-store",
topic: "report.saved",
method: "saveReport",
fromBlock: 10,
toBlock: 20,
limit: 25,
});
console.log(events.events[0]?.data);For a contract-scoped query:
const events = await client.contracts.eventsForContract("contract-report-store", {
topic: "report.saved",
order: "desc",
});Supported filters are contractId, topic, method, transactionHash, fromBlock, toBlock, limit, offset, and order.
Grant Bucket Access
Use client.contracts.grantBucketAccess(...) when a deployed contract principal needs bucket permissions:
await client.contracts.grantBucketAccess({
signer,
nonce: "auto",
submit: true,
contractId: "contract-report-store",
bucketId: "reports",
permissions: ["bucket:read_metadata"],
});This submits transaction GRANT_CONTRACT_BUCKET_ACCESS. Bucket concepts and permission names are covered in Data Buckets and Permission Model.
Register Packages
The SDK exposes helpers for registry transactions when a network requires registry approval before instantiation.
const registered = await client.contracts.registerPackage({
signer,
nonce: "auto",
package: contractPackage,
id: "pkg-typed-report-0.1.0",
auditMetadata: { audits: [{ name: "internal-review", result: "pass" }] },
approvalMetadata: { approvedFor: "production" },
});
await client.transactions.submit(registered.transaction);This builds transaction REGISTER_CONTRACT_PACKAGE.
Lower-level helpers are also available:
client.transactions.registerContractPackage(...);client.transactions.updateContractPackageStatus(...).
Use Contract Registry for registry status rules, matching fields, and review guidance.
Deactivate Contracts
Use client.contracts.deactivate(...) when a chain admin needs to stop a deployed contract from receiving direct or contract-to-contract calls:
const deactivation = await client.contracts.deactivate({
signer,
nonce: "auto",
submit: true,
contractId: "contract-report-store",
reason: "retired vulnerable package",
metadata: { incidentId: "inc-2026-05-31" },
});
console.log(deactivation.transaction.hash);This submits transaction DEACTIVATE_CONTRACT. It requires chain:admin, only works while the contract is active, and leaves a consensus audit trail on the contract row.
Contract Metrics
Operator clients can inspect contract execution metrics through the observability client:
const inventory = await client.observability.contracts();
const detail = await client.observability.contract("contract-report-store");
const failedCalls = await client.observability.contractCalls("contract-report-store", {
status: "failed",
fromBlock: 10,
limit: 25,
});These endpoints require the operator token. Metrics include calls, failures, fuel used, host calls, event counts, write counts, and runtime errors. They are operator diagnostics, not contract storage.
Tests
Run SDK tests:
npm run nooschain-ts:testRun package-level type coverage:
npm run nooschain-ts:buildRun monorepo type coverage after SDK API changes that may affect other apps:
npm run typecheck