npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@titon-network/atlas-sdk

v0.5.1

Published

TypeScript SDK for Atlas — TON-native threshold-BLS key backbone. Admit verifiers, receive GroupKeySync fan-outs, register automaton pkShares (G1 + G2 sibling, dlog-equality verified on-chain), bootstrap + rotate group keys. Per-operator + per-group G2 BL

Readme

@titon-network/atlas-sdk

Audience: Titon dev team building the next sibling product against Atlas. If you're working in titon/fortuna/, titon/phoebe/, or scaffolding a brand-new titon/<product>/ that needs threshold-BLS verification, this SDK is your contract handle, testing fixture, event decoder, and BLS off-chain helper rolled into one.

Not for end-user dapp authors — they consume the product SDKs (e.g. @titon-network/fortuna-sdk for VRF). Atlas is invisible infrastructure to them.

Audit status

🛡️ TSA-audited. Full report: AUDIT.md — 6 single-contract + 3 inter-contract TSA checkers + manual review + sandbox tests. 0 findings + 3 design observations.

| Layer | Result | |---|---| | TSA symbolic execution (@anthropic-ai/skills/ton-smart-contract-audit, v0.5.3) | 0 findings across 6 single-contract checkers (drain, bounce, replay + custom admitted-verifier-syncrequest, g2-dlog-acceptance, publish-groupkey-drain) and 3 inter-contract checkers (forgeton↔atlas drain, atlas↔fortuna grouppush, fortuna→atlas drain) | | Manual review against references/vulnerabilities.md | every receiver, every revert path | | Contract test suite (pnpm run test) | 216 / 216 passing (1 skipped) | | SDK test suite (pnpm run test:sdk) | 57 / 57 passing | | Cross-contract ABI byte-shape pin | tests/Integration.spec.ts exercises real ForgeTON AutomatonSync end-to-end — wire-level drift fails CI | | Coverage caveat | TSA v0.5.3 has a known STIR-opcode coverage gap on Tolk-1.3 storage-write paths; "0 results" is partial evidence rather than exhaustive proof. Compensated by manual review + concrete tests + cross-contract integration tests + 1000-iter property fuzz. See report for the honest evidence boundary. | | Pool-side foundation | Built on the TSA-audited @titon-network/forgeton-sdk (zero findings, 11 checkers + 262 contract tests + 192-iter fuzz). |

Live on TON mainnet (just bootstrapped 2026-05-18) and testnet. The SDK's ATLAS_MAINNET + ATLAS_TESTNET constants track the current contract addresses on each network — pick one, point your TonClient at the matching endpoint. See Connect — testnet vs mainnet below.

TypeScript surface for AtlasTON's threshold-BLS key backbone. One contract that owns the current group public key, the operator pkShare registry, timelocked rotation, and the verifier admission + GroupKeySync fan-out surface. Every Titon product that does threshold signatures consumes Atlas instead of re-implementing these primitives.

Atlas is the shared threshold-BLS substrate at the key-registry layer:

  • ForgeTON stakes the operators. Atlas mirrors the operator lifecycle via AutomatonSync fan-out.
  • Atlas owns the groupPk + pkShare registry. Each product admits itself via SetVerifier and caches the key.
  • Each product verifies sigs against the cached key and decides its own slashing reasons (sent through ForgeTON, not Atlas).

Atlas never slashes. Slashing is the consuming product's decision.

# In a new product repo, this SDK lives at file:../atlas/sdks/typescript via the workspace's
# zero-friction sibling-repo convention (per workspace CLAUDE.md):
pnpm add file:../atlas/sdks/typescript

@ton/core is a peer dependency — bring your own version (≥ 0.63.0).

Connect — testnet vs mainnet

The SDK is network-agnostic. You pick the network in two lines: the TonClient endpoint and which deployment constant you import.

// ── testnet ──────────────────────────────────────────────────────────
import { TonClient } from '@ton/ton';
import { Atlas, assertDeployment } from '@titon-network/atlas-sdk';

const tonClient = new TonClient({
    endpoint: 'https://testnet.toncenter.com/api/v2/jsonRPC',
});
const dep = assertDeployment('testnet');           // returns the testnet handle
const atlas = tonClient.open(Atlas.createFromAddress(dep.atlas));

For mainnet (live on TON since 2026-05-18), change exactly two lines:

// ── mainnet ──────────────────────────────────────────────────────────
const tonClient = new TonClient({
    endpoint: 'https://toncenter.com/api/v2/jsonRPC',                  // ← no `testnet.`
});
const dep = assertDeployment('mainnet');                                // ← was 'testnet'
const atlas = tonClient.open(Atlas.createFromAddress(dep.atlas));

That's it. Same npm package, same bytecode (mainnet code hash matches testnet), same code paths work on either network — only the TonClient endpoint and the deployment selector change. Prefer raw constants? Import ATLAS_MAINNET / ATLAS_TESTNET directly from @titon-network/atlas-sdk — both are populated.


The Titon-team product-build playbook

You're starting titon/<product>/. Four touch-points:

1. Verifier receiver — <product>/contracts/<product>.tolk

Implement a 0x51 GroupKeySync receiver that caches the key. Sender-pinned to storage.atlas, immutable post-deploy. Copy the wire struct from examples/verifier-template.tolk — do not retype. Bytewise drift = silent CellUnderflow on every fan-out land.

// `groupPkG2` is a `Cell<bits768>` ref-cell sibling (Tolk's auto-serializer
// encodes that as a ref to a 768-bit cell with no header, so no wrapper
// struct is needed). Keep the field even if your product only does G1-style
// `BLS_VERIFY` against `groupPk`; dropping it shifts the trailing bits and
// breaks parse, and adopting ChallengeReveal-style cryptographic gates
// later (Themis pattern) requires the G2 form.
struct (0x00000051) GroupKeySync {
    groupId:     uint8
    groupPk:     bits384
    groupPkG2:   Cell<bits768>
    groupEpoch:  uint32
    threshold:   uint8
    memberCount: uint8
}

fun handleGroupKeySync(msg: GroupKeySync, sender: address) {
    assert (sender == storage.atlas) throw E_NOT_ATLAS;       // #1 footgun if missing
    assert (msg.groupId == 0) throw E_BAD_GROUP;              // v1 single-group
    storage.groupPk     = msg.groupPk;
    storage.groupPkG2   = msg.groupPkG2;
    storage.groupEpoch  = msg.groupEpoch;
    storage.threshold   = msg.threshold;
    storage.memberCount = msg.memberCount;
    storage.save();
}

The full template covers SyncRequest bootstrap pull + a stub handleFulfill that runs BLS_VERIFY(storage.groupPk, msg, sig) with the receiver-safety banner up top. Or run npx atlas generate verifier --type groupkey-cache.

2. Atlas pin — same file

struct AtlasStorage {  // your product's storage, abbreviated
    schemaVersion: uint8
    atlas:         address    // pinned at deploy; immutable post-deploy
    forgeton:      address    // ditto if your product slashes
    groupPk:       bits384
    groupPkG2:     Cell<bits768>   // G2 sibling — cache it even if you don't use it now
    groupEpoch:    uint32
    threshold:     uint8
    memberCount:   uint8
    // ...product-specific fields
}

A mutable atlas field is a spoof vector. Only ever change it via your product's own 3-step timelocked code upgrade.

3. Slash through ForgeTON, not Atlas

If your product detects a fault (missed fulfill, stale feed, invalid VRF), send Slash (op 0x14) directly to ForgeTON with your product's own reason: uint32 namespace:

struct (0x00000014) Slash {
    automaton: address
    reason:    uint32      // YOUR product's namespace (e.g. 1 = INVALID_VRF)
    ctx:       uint64      // YOUR product's context (e.g. requestId)
    amount:    coins       // capped at consumer.maxSlashPerEvent
}

Reference: titon/kronos/contracts/kronos-registry.tolk (REASON_MISSED_EXECUTION = 1). Atlas is out of the slash path entirely.

4. Tests — <product>/tests/Integration.spec.ts

import { Blockchain } from '@ton/sandbox';
import { deployAtlasFixture } from '@titon-network/atlas-sdk/testing';
import { ForgeTON, loadForgetonCode } from '@titon-network/forgeton-sdk';

const blockchain = await Blockchain.create();
const { atlas, admitVerifier, rotate, groupSk, groupPk, groupPkG2 } =
    await deployAtlasFixture(blockchain);

// Deploy your product, admit it as a verifier:
await admitVerifier({ contract: myProduct.address });

// Exercise rotation — your product's 0x51 receiver should now hold newPk + newPkG2 at newEpoch
const { sk: newSk, pk: newPk, pkG2: newPkG2, newEpoch } = await rotate();

See atlas/tests/Integration.spec.ts for the cross-contract test pattern with a real ForgeTON.

That's the entire integration. Key management, rotation, operator set drift, fan-out — handled by Atlas + the pool. You write the verifier receiver + your product-specific fulfill logic.


Public surface

┌─────────────────────────────────────────────────────────────┐
│ explainError   AtlasError   summarizeTx   formatTxSummary   │  diagnostics
├─────────────────────────────────────────────────────────────┤
│ decodeEvent    decodeEvents    tryDecodeEvent               │  events
├─────────────────────────────────────────────────────────────┤
│ Atlas          newAtlas        ATLAS_DEFAULTS               │  contract + factory
├─────────────────────────────────────────────────────────────┤
│ generateGroupKey  signMessage  aggregateSignatures          │  BLS helpers (off-chain aggregator)
├─────────────────────────────────────────────────────────────┤
│ deployAtlasFixture                                          │  testing/ subpath
├─────────────────────────────────────────────────────────────┤
│ OP   ERR   loadAtlasCode   ATLAS_TESTNET                    │  constants + artifacts
└─────────────────────────────────────────────────────────────┘

No façade, no fluent builder — the surface is small by design. Atlas has one role (threshold-BLS key backbone); integrate at the ABI level.


Fan-out cost — sizing your tests' value: parameters

| Item | Default | Updatable? | Paid for | |------|---------|-----------|----------| | verifierSyncValue | 0.05 TON | via UpdateConfig | Per-verifier forward on fan-out (Atlas → your verifier receiver) | | minStorageReserve | 0.1 TON | via UpdateConfig | Atlas's own rent floor (enforced before any outbound) | | minGasForRegister | 0.05 TON | via UpdateConfig | RegisterBlsShare / DeregisterBlsShare gas floor | | minGasForSyncRequest | 0.05 TON | via UpdateConfig | Verifier-inbound SyncRequest gas floor | | minGasForRotation | 0.1 TON | deploy-only (code upgrade to change) | Base overhead on Execute rotation (plus per-verifier fan-out) |

On rotation Execute, the value Atlas needs is minGasForRotation + verifierCount * verifierSyncValue. Always size via atlas.getRequiredRotationValue() — never hardcode (an owner-side UpdateConfig would silently break you).


Quickstart — typical flow when bringing up a new product locally

Spin up Atlas in your tests

import { Blockchain } from '@ton/sandbox';
import { deployAtlasFixture } from '@titon-network/atlas-sdk/testing';

const blockchain = await Blockchain.create();
const { atlas, admitVerifier, rotate, automatonSync, bootstrapSoloGroup, groupSk, groupPk } =
    await deployAtlasFixture(blockchain);
// atlas is live: groupPk published, one operator registered. Ready for admit + fan-out tests.

Deploy a fresh Atlas (production / testnet)

This is rarely needed during product development — one Atlas instance serves N products. Here for completeness:

import { TonClient } from '@ton/ton';
import { toNano } from '@ton/core';
import { newAtlas } from '@titon-network/atlas-sdk';

const tonClient = new TonClient({ endpoint: 'https://testnet.toncenter.com/api/v2/jsonRPC' });
const atlas = tonClient.open(newAtlas({
    owner: ownerAddress,
    forgeton: forgetonPoolAddress,  // pinned at deploy; repoint via code upgrade
}));

await atlas.sendDeploy(ownerSender, toNano('1'));
console.log('Atlas deployed at', atlas.address.toString());

Post-deploy:

  1. Off-chain DKG ceremony across the automaton set → aggregate groupPk (G1, 48 bytes) + groupPkG2 (G2, 96 bytes) + per-automaton sk_i + pkShare_i + pkShareG2_i. For dev / demos, use generateGroupKey() which returns all three forms bound to one sk (solo mode below).
  2. Publish both halves via atlas.sendPublishGroupKey(... { groupPk, groupPkG2 }).
  3. Each automaton calls RegisterBlsShare with { pkShare, pkShareG2 } after its AutomatonSync mirrors in from ForgeTON. Atlas runs a pairing-equality gate that proves both halves come from one secret (E_G1_G2_DLOG_MISMATCH = 163).
  4. Admit your product(s) via atlas.sendSetVerifier(owner, { contract: myProduct.address, isActive: true, subscribedGroups: 1n }).

Solo-oracle mode (tests + dev / demo)

import { generateGroupKey, signMessage } from '@titon-network/atlas-sdk';

const { sk, pk, pkG2 } = generateGroupKey();   // 32-byte sk, 48-byte G1 pk, 96-byte G2 sibling
// Publish (pk, pkG2) as (groupPk, groupPkG2) AND register the same pair as
// the sole (pkShare, pkShareG2). Atlas solo-mode enforces equality on BOTH
// halves (E_SOLO_PK_SHARE_MISMATCH=161, E_SOLO_PK_SHARE_G2_MISMATCH=164).
// Sign with signMessage(sk, msg); the BLS_DST_G2_POP DST is bound in.

Not for mainnet value. One secret key = one point of failure. Standard pattern in every Titon product's unit-test suite. See skills/atlas-deploy.md for a real DKG bootstrap.

Rotate the group key

Owner, 3-step, 24h timelock:

await atlas.sendPause(owner, { value: toNano('0.05') });
await atlas.sendProposeGroupKeyRotation(owner, {
    value: toNano('0.1'),
    newGroupPk: Buffer.from(newPk),
    newGroupPkG2: Buffer.from(newPkG2),  // same secret as newGroupPk
    newThreshold,
    newMemberCount,
    delaySeconds: 24 * 3600,
});

// ...24h later...

const value = await atlas.getRequiredRotationValue();   // minGasForRotation + verifierCount * verifierSyncValue
await atlas.sendExecuteGroupKeyRotation(owner, { value });
await atlas.sendUnpause(owner, { value: toNano('0.05') });

Execute fans out GroupKeySync to every admitted + subscribed verifier. Operators must re-register their new-epoch pkShares before the group accepts fulfills again — the dense operator index is cleared on rotation.

Decode Atlas events (during integration tests + telemetry)

import { decodeEvents, AtlasEvent } from '@titon-network/atlas-sdk';

for (const tx of result.transactions) {
    const externalOuts = [...tx.outMessages.values()]
        .filter((m) => m.info.type === 'external-out')
        .map((m) => m.body);

    for (const ev of decodeEvents(externalOuts)) {
        switch (ev.kind) {
            case 'GroupKeyPublished':
                console.log(`group ${ev.groupId} bootstrapped at epoch ${ev.groupEpoch}`);
                break;
            case 'VerifierSynced':
                console.log(`fan-out landed at ${ev.verifier}`);
                break;
            case 'OperatorActivationChanged':
                console.log(`${ev.automaton} isActive=${ev.isActive} cause=${ev.cause}`);
                break;
        }
    }
}

Or use the one-shot summarizer:

import { summarizeTxs, formatTxSummary } from '@titon-network/atlas-sdk';
for (const s of summarizeTxs(result.transactions)) {
    console.log(formatTxSummary(s));
    // [ok] events: GroupKeyPublished, VerifierSynced
    // [fail] exit 220 RotationRequiresPause — ProposeGroupKeyRotation requires …
}

Interpret exit codes during cross-contract tests

import { explainError } from '@titon-network/atlas-sdk';

const e = explainError(220);
// {
//   code: 220,
//   origin: 'atlas',
//   name: 'RotationRequiresPause',
//   message: 'ProposeGroupKeyRotation / ExecuteGroupKeyRotation requires the contract to be paused.',
//   hint: 'Owner must sendPause first. Pause prevents new operator ops + request flows from racing the epoch bump.',
// }

Atlas surfaces TVM's common codes too (9 CellUnderflow, 13 OutOfGas, 37 NotEnoughTon, 0xFFFF UnknownOpcode).


CLI

The SDK ships a small atlas CLI for local introspection + product scaffolding. All commands accept --json for machine-readable output.

Scaffolding

$ npx atlas init                                     # write ATLAS.md (agent context for your product repo)
$ npx atlas generate verifier --type groupkey-cache  # scaffold a Tolk verifier
$ npx atlas generate verifier --out myVerifier.tolk --force

Introspection (no network)

$ atlas explain 220
exit 220 (atlas): RotationRequiresPause
  ProposeGroupKeyRotation / ExecuteGroupKeyRotation requires the contract to be paused.
  hint: Owner must sendPause first. Pause prevents new operator ops …

$ atlas schema
SDK expects:
  ATLAS_STORAGE_VERSION:       1
  ...
  BLS:
    pubkey bytes:  48 (G1)
    sig bytes:     96 (G2)
    DST:           BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_

$ atlas hash
hex:    <bundled artifact code hash>

$ atlas decode <hex-boc>             # decode an emitted AtlasEvent cell

Live (needs pnpm add @ton/ton)

$ atlas info <atlas-addr> --testnet
$ atlas estimate fanout --atlas <addr> --testnet
$ atlas estimate rotation --atlas <addr> --testnet
$ atlas verify --testnet                 # drift-check SDK vs canonical deploy

The BLS ciphersuite (your product's aggregator side)

Atlas's operator pkShare registry + GroupKeySync carry G1 points under min-pk:

  • Pubkeys (G1): 48 bytes compressed
  • Signatures (G2, used by your fulfill receiver): 96 bytes compressed
  • Domain-separation tag: BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_

@noble/curves/bls12-381's default DST is _NUL_ — that does NOT match TVM. Off-chain signers must pass BLS_DST_G2_POP (exported from @titon-network/atlas-sdk) explicitly to bls.longSignatures.hash(). The SDK's signMessage(sk, msg) helper binds the DST in for you.

import { signMessage } from '@titon-network/atlas-sdk';
const sig = signMessage(sk, msgBytes);  // 96-byte G2 compressed

What's where

| File | Purpose | |------|---------| | src/contracts/Atlas.ts | Atlas class — ABI wrapper with send/get methods, SchemaDriftError, validateConfig, validateSetVerifier, validateAgainstLive, gas estimators | | src/opcodes.ts | OP + ERR constants + schema versions + BLS ciphersuite constants + protocol limits | | src/errors.ts | explainError(code) + AtlasError — covers Atlas (100-249, 333) and common TVM codes | | src/events/ | Typed AtlasEvent union + decodeEvent / decodeEvents / tryDecodeEvent | | src/factory.ts | newAtlas({ owner, forgeton }) — one-line deploy handle | | src/solo.ts | generateGroupKey + signMessage + aggregateSignatures — BLS helpers with the correct DST bound in | | src/testing/ | deployAtlasFixture — one-line sandbox setup. Imported via @titon-network/atlas-sdk/testing subpath | | src/diagnostics.ts | summarizeTx / formatTxSummary — collapse a Transaction to its useful fields | | src/artifacts/loader.ts | loadAtlasCode() + ATLAS_CODE_HASH | | src/deployments.ts | ATLAS_TESTNET / ATLAS_MAINNET canonical addresses + assertDeployment() loud-error helper | | src/cli.ts | atlas CLI | | ERRORS.md | Flat Markdown table of every exit code. Generated. | | OPCODES.md | Flat Markdown table of every wire opcode. Generated. | | llms.txt | Single-page AI-assistant context | | AGENTS.md | Surface map + skills index | | templates/agent-context.md | Dense AI primer — generated into a product repo by npx atlas init | | examples/verifier-template.tolk | Canonical starting point for a new product's 0x51 receiver | | skills/ | Seven persona-grouped task playbooks |


Schema drift

Persistent structs (AtlasStorage, AtlasConfig, VerifierRegistry, VerifierInfo, OperatorInfo, GroupBlob, OperatorShare) carry a schemaVersion: uint8 first field. The SDK's validateAgainstLive() verifies every version in one call and throws SchemaDriftError on mismatch — surface this as "upgrade the SDK or the contract", not as a silent null. See atlas verify --testnet.


Status

Mainnet (live since 2026-05-18):

Testnet (clean-launch reference state):

SDK: @titon-network/[email protected] (this package — carries G2 sibling for ChallengeReveal-readiness at consumer products). Both ATLAS_MAINNET and ATLAS_TESTNET constants are populated.

import { assertDeployment, Atlas } from '@titon-network/atlas-sdk';
const dep = assertDeployment('mainnet');           // or 'testnet'
const atlas = tonClient.open(Atlas.createFromAddress(dep.atlas));

Cross-repo workspace links

License

MIT.