Build Quantum applications in TypeScript.
The JavaScript SDK validates networks, prepares transactions, delegates all cryptography to the controlled native package, submits raw bytes, and waits for receipts. RPC-free entrypoints support adapters that already own submission and lifecycle handling.
Install two controlled packages.
Node.js 22 and 24 LTS are supported. Normal consumers receive the platform-specific native addon through the private npm packages and do not need CMake, a compiler, or a system cryptography installation.
mkdir quantum-javascript-demo
cd quantum-javascript-demo
npm init -y
npm install @quantum_chain/sdk@2.1.0 @quantum_chain/pqc@0.1.0
npm install --save-dev tsx typescript @types/nodeConfigure the read-only npm token outside application source:
@quantum_chain:registry=https://registry.npmjs.org/
//registry.npmjs.org/:_authToken=${NPM_TOKEN}Generate, fund, send, and confirm.
import {
QuantumClient,
QuantumWallet,
formatQuantum,
networks,
parseQuantum,
} from "@quantum_chain/sdk";
const client = new QuantumClient(networks.sandbox);
const sender = QuantumWallet.generate();
const recipient = QuantumWallet.generate();
try {
const network = await client.validateNetwork();
console.log("network", network.network, network.chainId.toString());
console.log("sender", sender.address);
const funding = await client.sandbox!.fund(sender.address);
console.log("balance", formatQuantum(funding.balance), "QUANTUM");
const submitted = await sender.sendTransaction(client, {
to: recipient.address,
value: parseQuantum("0.01"),
});
console.log("transaction", submitted.hash);
const receipt = await submitted.wait({
confirmations: 1,
timeoutMs: 120_000,
pollIntervalMs: 1_000,
});
console.log("status", receipt.status);
console.log("block", receipt.blockNumber.toString());
console.log("explorer", client.getExplorerTxUrl(submitted.hash));
} finally {
sender.destroy();
recipient.destroy();
}npx tsx send.tsThe script validates chain ID and genesis, creates disposable native signers, uses the test-only faucet, resolves the pending nonce and fees, estimates gas, signs the exact digest, submits once, and requires a successful receipt.
Import only the layer you own.
| Import | Purpose | RPC |
|---|---|---|
@quantum_chain/sdk | Full client, wallet, contracts, transactions, networks, and utilities | Client and wallet methods may call RPC |
@quantum_chain/sdk/transactions | Construction, signing orchestration, serialization, hashing, and units | No |
@quantum_chain/sdk/signers | QuantumSigner and local native signer | No |
@quantum_chain/sdk/rpc | Client, HTTP transport, request types, response types, and RPC errors | Yes |
Use the root package for an application that wants the complete lifecycle. Use the transaction and signer subpaths when an adapter supplies resolved transaction fields and owns submission.
Typed chain access and network validation.
new QuantumClient(config: QuantumClientConfig | QuantumNetwork)Important configuration fields are chainId, rpcUrl, network, genesisHash, explorerUrl, faucetUrl, namespace, transport, and bounded HTTP transport options.
getChainId(options?)Promise<bigint>detectNetwork(options?)detected chain ID, genesis, and known-network resultvalidateNetwork(options?)verified configured network identitygetBalance(address, block?)Promise<bigint>getTransactionCount(address, block?)Promise<bigint>getGasPrice()Promise<bigint>getMaxPriorityFeePerGas()Promise<bigint>estimateGas(call)Promise<bigint>call(call, block?)Promise<Uint8Array>getCode(address, block?)Promise<Uint8Array>getBlockNumber()Promise<bigint>getBlockByNumber(block, full?)normalized block or nullgetBlockByHash(hash, full?)normalized block or nullgetTransaction(hash)transaction or nullgetTransactionReceipt(hash)receipt or nullprepareTransaction(from, request)resolved unsigned transactionbroadcastTransaction(signed)QuantumTransactionResponseOn the Sandbox preset, client.sandbox.fund(address) returns the address, current balance, target balance, whether it created a funding transaction, and an optional funding hash.
Bind a signer to an address and transaction lifecycle.
QuantumWallet.generate()QuantumWallet.fromPrivateKey(privateKey)await QuantumWallet.fromSigner(signer)wallet.addressnormalized 20-byte address stringwallet.publicKeydefensive-copy Uint8ArraysignTransaction(client, request)prepared and signed transactionsignPrepared(client, transaction)signed transaction from resolved fieldssendTransaction(client, request)submitted response with hash and wait()anchorHash(client, anchor)canonical hash-anchor transactionresetNonce()invalidate local automatic nonce statedestroy()erase local signer state where supportedgenerate() is convenient for tutorials and short-lived tools. Production systems should provide an approved QuantumSigner through fromSigner(). Do not export, log, or persist private-key bytes from examples.Return everything an external adapter needs.
import {
buildAndSignTransaction,
parseQuantum,
} from "@quantum_chain/sdk/transactions";
import { LocalPQCSigner } from "@quantum_chain/sdk/signers";
const signer = new LocalPQCSigner();
try {
const result = await buildAndSignTransaction({
type: "legacy",
chainId: 20804n,
nonce: 12n,
gasLimit: 21_000n,
gasPrice: 1_000_000_000n,
to: "0x0000000000000000000000000000000000000001",
value: parseQuantum("1"),
}, signer);
console.log(result.rawTransaction);
console.log(result.transactionHash);
console.log(result.publicKey);
console.log(result.signature);
console.log(result.signingDigest);
} finally {
signer.destroy();
}Exact result
interface SignTransactionResult {
unsignedTransaction: UnsignedQuantumTransaction;
signedTransaction: SignedQuantumTransaction;
signingDigest: Uint8Array;
signature: Uint8Array;
publicKey: Uint8Array;
rawTransaction: `0x${string}`;
rawTransactionBytes: Uint8Array;
transactionHash: `0x${string}`;
}buildTransaction, signTransaction, and buildAndSignTransaction perform no RPC. The caller supplies resolved nonce, gas, and fee fields and owns broadcast, retry policy, and receipts.
Keep callers independent from key storage.
interface QuantumSigner {
getPublicKey(): Promise<Uint8Array>;
signDigest(digest: Uint8Array): Promise<Uint8Array>;
}The transaction layer sends exactly one 32-byte digest to the signer. It validates public-key and signature lengths and verifies the returned signature with the native package before attaching it. A remote, hardware-backed, or process-isolated signer can replace LocalPQCSigner without changing transaction callers.
Utilities
parseQuantum, formatQuantum, bytesToHex, hexToBytes, toQuantity, fromQuantity, normalizeAddress, normalizeHash, networks.sandbox, and networks.mainnet cover common boundaries. Binary inputs stay binary and integer values use bigint.
Failures are typed and never trigger a crypto fallback.
All SDK errors extend QuantumError. Exported classes include ChainIdMismatchError, GenesisMismatchError, NetworkMismatchError, InvalidAddressError, InvalidTransactionError, SerializationError, SigningError, RpcError, RpcResponseError, RpcTransportError, TransactionRejectedError, TransactionRevertedError, and TransactionTimeoutError.
- Call
validateNetwork()before any sending workflow. - Keep quantities as
bigintand binary values asUint8Array. - Do not retry a write until you reconcile its local transaction hash and pending nonce.
- Call
destroy()for local tutorial wallets in afinallyblock. - Use controlled lockfiles and approved private package versions.