TypeScript SDK
Use the first-party Starkscan TypeScript client when you want typed explorer reads in application code.
Use the first-party Starkscan TypeScript client when you want typed explorer reads in application code.
Use the TypeScript SDK when you want typed Starkscan reads in application code without rebuilding the HTTP contract yourself.
Use the live explorer when you want to see the same entities first:
npm install @mezcal/sdk@alpha
pnpm add @mezcal/sdk@alpha
bun add @mezcal/sdk@alpha
Current public channel today: @alpha
Release channels:
alpha: fastest-moving public channelbeta: stabilization channellatest: current generally recommended channel once promotednpm install ./mezcal-sdk-<version>.tgz
Use the tarball flow only when you need controlled distribution or release verification. Public npm publishing uses the same @mezcal/sdk package name and API surface, so you can switch install channels without changing your application code.
For hosted external deployments, set MEZCAL_BASE_URL to the deployment’s /api base, for example https://<your-mezcal-host>/api.
The SDK keeps using the normal /v1/* route paths under that configured base.
import { createStarkscanClient } from "@mezcal/sdk";
const mezcal = createStarkscanClient({
apiKey: process.env.MEZCAL_API_KEY!,
baseUrl: process.env.MEZCAL_BASE_URL!,
chainId: "SN_MAIN",
});
const status = await mezcal.status();
const block = await mezcal.block("1234");
const totalSupply = await mezcal.tokenTotalSupply("0xtoken");
const balance = await mezcal.tokenBalanceOf("0xtoken", "0xowner");
Use block reads when your application starts from a block number or block hash and needs canonical block contents.
const block = await mezcal.block(8279910, 5);
const txs = await mezcal.blockTransactions(8279910, undefined, 25);
for (const item of txs.items) {
console.log(item.txIndex, item.txHash, item.finalityStatus);
}
mezcal.block accepts a block number, block hash, or "latest". blockTransactions requires a concrete block number; resolve "latest" or a block hash with mezcal.block(...) first, then pass the returned blockNumber with nextCursor. The hosted SDK does not expose per-block event or receipt pages; use transaction detail reads after resolving the block transaction list.
const wallets = ["0xwalletA", "0xwalletB"];
const activity = await Promise.all(
wallets.map((wallet) => mezcal.addressActivity(wallet, undefined, 50)),
);
const transactions = await Promise.all(
wallets.map((wallet) => mezcal.addressTransactions(wallet, undefined, 50)),
);
const holdings = await Promise.all(
wallets.map((wallet) => mezcal.addressTokenHoldings(wallet)),
);
const flows = await mezcal.tokenTransfers("0xtoken", {
addresses: wallets,
limit: 100,
});
Use that pattern when you are monitoring a handful of wallets and need recent activity, recent transactions, current holdings, and token-scoped inflow/outflow reads from the same client.
For the full external starter, including the shared env contract and the matching REST and CLI flows, use Monitor 10 wallets.
const totalSupply = await mezcal.tokenTotalSupply("0x0123...");
const pendingSupply = await mezcal.tokenTotalSupply("0x0123...", "pending");
const balance = await mezcal.tokenBalanceOf("0x0123...", "0x0456...");
const transfers = await mezcal.tokenTransfers("0x0123...", {
addresses: ["0x0456...", "0x0789..."],
fromBlock: 7_800_000,
toBlock: 7_802_500,
});
const transfers = await mezcal.tokenTransfers("0x0123...", {
addresses: ["0xwalletA", "0xwalletB"],
fromBlock: 7_800_000,
toBlock: 7_801_000,
limit: 100,
});
for (const item of transfers.items) {
console.log(item.timestampIso, item.txHash, item.rawValue);
}
const events = await mezcal.contractEvents("0xcontract", {
topic0: "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9",
fromBlock: 7_800_000,
toBlock: 7_800_500,
limit: 100,
});
for (const item of events.items) {
console.log(item.blockNumber, item.txHash, item.logIndex, item.topic0);
}
Use contractEvents when you need the canonical paginated event stream for one contract before applying protocol-specific decoding or position logic. Keep filters server-side first: contract address, exact topic0..topic3, block range, then cursor pagination with nextCursor.
const batch = await mezcal.txDetails(["0xabc...", "0xdef..."], {
logLimitPerTx: 32,
});
for (const tx of batch.items) {
console.log(
tx.txHash,
tx.blockNumber,
tx.logs.length,
tx.tokenTransfers.length,
);
}
Use txDetails when you already have an ordered tx hash list and want bounded Starkscan transaction previews in one batch. Check logsTruncated and tokenTransfersTruncated before treating child arrays as exhaustive.
It keeps: