SDK Guide
The thesislock-sdk package wraps the Clarity serialization and Hiro reads for JavaScript and TypeScript projects. It is read-only: it verifies existing anchors and reads history. Creating anchors needs a wallet and is done in the web app.
Installation
The SDK targets Node.js 18 or newer (it uses the global fetch and node:crypto).
npm install thesislock-sdkQuick start
import { createClient } from 'thesislock-sdk';
const client = createClient();
const result = await client.verify('9afe6f57ea2af60478ad37b2d44ae8ede492c4f3b7e70bcc7dfea92128585d06');
if (result.verified) {
console.log('Anchored by', result.data.anchoredBy);
console.log('Stacks block', result.data.stacksBlock);
}Configuration
Both createClient(config?) and new ThesisLockClient(config?) accept an optional config object:
| Option | Default | Description |
|---|---|---|
apiUrl | https://api.mainnet.hiro.so | Base URL of the Hiro Stacks API used for read-only calls. |
contractAddress | SP3QS6X01...88FNVM | Principal that deployed the ThesisLock contracts. |
network | mainnet | Network label, mainnet or testnet. |
import { ThesisLockClient } from 'thesislock-sdk';
const client = new ThesisLockClient({
apiUrl: 'https://api.mainnet.hiro.so',
contractAddress: 'SP3QS6X01XKTYC84BHA0J567CZTAH67BJHN88FNVM',
});Client methods
All methods return Promises. A failed network call or a contract rejection throws an Error; a plain "not found" is not an error, it resolves to an unverified result or null.
verify(hash)
Looks up a single anchor in thesislock.
const result = await client.verify(hash);
// { verified: true, source: 'single', data: AnchorResult }
// or { verified: false, source: null, data: null }verifyBatch(hash, owner)
Looks up an owner-keyed batch anchor in thesislock-batch. The owner is required because batch anchors are keyed by hash and owner. Throws if owner is not a valid Stacks principal.
const result = await client.verifyBatch(hash, 'SP3QS6X01XKTYC84BHA0J567CZTAH67BJHN88FNVM');
// { verified: true, source: 'batch', data: BatchAnchorResult }verifyAny(hash, owner?)
Tries the single anchor first, then the batch anchor when an owner is given. Returns the first match, or an unverified result.
const result = await client.verifyAny(hash, owner);getAnchorCount(owner) and getRecentAnchors(owner)
Read per-principal registry data. getAnchorCount returns how many anchors a principal has registered; getRecentAnchors returns up to the ten most recent entries, newest first.
const count = await client.getAnchorCount(owner);
const entries = await client.getRecentAnchors(owner); // RegistryEntry[]getProof(tokenId) and getProofByHash(hash)
Read soulbound proof NFTs from thesislock-proof. Both return null when nothing matches.
const proof = await client.getProof(1); // ProofNFT | null
const byHash = await client.getProofByHash(hash); // ProofNFT | nullUtility functions
These are exported at the top level and do not need a client.
| Function | Returns |
|---|---|
hashString(input) | Lowercase 64-char hex SHA-256 of a string's UTF-8 bytes. |
hashFile(file) | SHA-256 hex of a File or Buffer (async). |
isValidHash(hash) | True when input is 64 hex chars (an optional 0x prefix and uppercase are accepted). |
serializeHash(hex) | Encodes a hash as a serialized (buff 32) value, hex without 0x prefix. |
truncateHash(hash, chars?) | Shortens a hash to first and last chars (default 8) for display. |
import { hashFile, truncateHash } from 'thesislock-sdk';
import { readFileSync } from 'node:fs';
const hash = await hashFile(readFileSync('thesis.pdf'));
console.log(truncateHash(hash, 4)); // '9afe...5d06'Error handling
A failed network request or a contract rejection throws an Error; a plain "not found" does not. Wrap calls in try/catch for outages, and check verified (or a null return) for the not-found case. verifyBatch, getAnchorCount, and getRecentAnchors also throw on an invalid principal, and getProof throws on a negative or non-integer token id.
try {
const result = await client.verify(hash);
console.log(result.verified ? 'Anchored' : 'Not anchored');
} catch (err) {
console.error('Lookup failed:', err);
}Examples
Runnable scripts live in the sdk/examples directory: verify-hash.ts (verify one hash), check-wallet.ts (a wallet's anchor count and recent anchors), hash-and-verify.ts (hash a local file then verify it), and batch-check.ts (verify a list of hashes). Run any with npx ts-node examples/<name>.ts.
Types
AnchorResult, BatchAnchorResult, RegistryEntry, ProofNFT, and VerifyResult are exported. VerifyResult is a discriminated union, so checking result.verified narrows data with no casts.
type VerifyResult =
| { verified: true; source: 'single'; data: AnchorResult }
| { verified: true; source: 'batch'; data: BatchAnchorResult }
| { verified: false; source: null; data: null };
const result = await client.verify(hash);
if (result.verified) {
result.data.anchoredBy; // narrowed to AnchorResult
}Prefer the terminal or a hosted endpoint? See the CLI Guide and the REST API.