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

@terminal3/t3n-sdk

v4.10.1

Published

T3n TypeScript SDK - A minimal SDK that mirrors the server's RPC handler approach

Downloads

6,951

Readme

T3n TypeScript SDK

A minimal TypeScript SDK that mirrors the server's RPC handler approach, keeping all state machine logic hidden in WASM and providing a clean, agnostic wrapper that doesn't expose authentication methods or internal states.

Features

  • Simple API: Clean, minimal interface that's easy to use
  • Method Agnostic: Supports multiple authentication methods (Ethereum, OIDC) without exposing implementation details
  • WASM-Powered: All cryptographic complexity and state machine logic isolated in WASM components
  • Type Safe: Full TypeScript support with comprehensive type definitions
  • Secure: Encrypted communication with T3n nodes

Installation

pnpm add @terminal3/t3n-sdk

Quick Start

Prerequisites: a T3 account and your T3 API key — the private key of the ETH wallet you registered with. The key never leaves your machine; it's used locally to sign the login challenge.

Don't have these yet? It's self-serve — no approval or waitlist. Claim your account, API key, and test tokens at https://www.terminal3.io/claim-page (sign in with your work email; your key is issued instantly).

Basic Usage

import {
  T3nClient,
  loadWasmComponent,
  createEthAuthInput,
  eth_get_address,
  metamask_sign,
} from "@terminal3/t3n-sdk";

const wasmComponent = await loadWasmComponent();
const privateKey = process.env.T3N_DEMO_KEY!;
const address = eth_get_address(privateKey);

const client = new T3nClient({
  baseUrl: "https://t3n-node.example.com",
  wasmComponent,
  handlers: {
    EthSign: metamask_sign(address, undefined, privateKey),
  },
});

await client.handshake();

const did = await client.authenticate(
  createEthAuthInput(eth_get_address(privateKey))
);

Ethereum Authentication

import {
  T3nClient,
  loadWasmComponent,
  createEthAuthInput,
  eth_get_address,
  metamask_sign,
} from "@terminal3/t3n-sdk";

const privateKey = "0x...";
const address = eth_get_address(privateKey);

const client = new T3nClient({
  wasmComponent: await loadWasmComponent(),
  handlers: {
    EthSign: metamask_sign(address, undefined, privateKey),
  },
});

await client.handshake();
const did = await client.authenticate(
  createEthAuthInput(eth_get_address(privateKey))
);

OIDC Authentication

import { createOidcAuthInput } from "@terminal3/t3n-sdk";

// `client` is an already-handshaked T3nClient (see Quick Start above).
const did = await client.authenticate(
  createOidcAuthInput({
    provider: "google",
    // The T3n node mints a session-binding nonce. Pass it to your provider's
    // authorization request and return the resulting id_token JWT.
    getIdToken: async (nonce) => getGoogleIdToken({ nonce }),
  })
);

Environments

The SDK targets the public T3n networks.

  • sandbox — the public test network, for integration and pre-production use.
  • production — the public mainnet network.

Select the network with setEnvironment("sandbox" | "production") — this sets the default node used by clients created afterwards. To target a specific node, pass an explicit baseUrl to new T3nClient({ baseUrl, … }); baseUrl takes precedence over the environment default.

OTP-backed user flows

@terminal3/t3n-sdk ships typed helpers for the explicit OTP roundtrip and the slim Level-1 user-input ingest:

  • client.otpRequest — request and dispatch an OTP code to an email or SMS channel.
  • client.otpVerify — redeem an OTP and bind the verified contact.
  • client.submitUserInput — Level-1 user-input ingest. Rejects callers without a verified email with the typed UserUpsertError({ kind: "EmailNotVerified" }).
import { T3nClient, UserUpsertError } from "@terminal3/t3n-sdk";

// 1) Bind the user's email via OTP.
const requested = await client.otpRequest({
  emailChannel: { emailAddress: "[email protected]" },
});
const code = await prompt(`Code sent to ${requested.contact}: `);
await client.otpVerify({
  otpCode: code,
  request: { emailChannel: { emailAddress: "[email protected]" } },
});

// 2) Slim user-upsert: Level-1 user-input ingest.
try {
  const result = await client.submitUserInput({
    profile: {
      first_name: "Alice",
      last_name: "Smith",
      country_of_residence: "US",
    },
  });
  console.log("tx:", result.txHash);
} catch (err) {
  if (err instanceof UserUpsertError && err.kind === "EmailNotVerified") {
    // run otpRequest + otpVerify, then retry.
  }
  throw err;
}

For tests that "just want it to work", runOtpThenUserInput chains the three calls behind a single getOtpCode callback.

Email-OTP login: skip the user-layer OTP

The example above is for a wallet / OIDC session proving an email for the first time. If the session instead logged in via email-OTP (authenticate(createEmailOtpAuthInput(...))), the node already proved that email during login and sent the only OTP code. For that email, submitUserInput passes the verified-email gate on the session authenticator alone and the node auto-stamps verified_contacts.email — so call it directly, with no otpRequest / otpVerify in between (those would send a redundant second OTP email). Use the user-layer OTP only to verify a contact the session has not already proven — a phone, or an email on a wallet/OIDC session.

License

MIT