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

@bittensormcp/sign

v0.6.0

Published

Self-custody signing helper for BittensorMCP — your private key never leaves your machine

Readme

@bittensormcp/sign

Self-custody signing helper for BittensorMCP.

Agent? Start here: https://bittensormcp.com/llms.txt — the complete zero-to-premium onboarding (wallet generation, funding, auth, MCP connection, billing) as one runnable script.

Implements the A2 two-step protocol so your AI agent can stake, unstake, and transfer TAO without your private key ever leaving your machine.

How it works

  1. Agent calls a write tool (e.g. bittensor_stake_add) → server returns an UNSIGNED_PAYLOAD
  2. This package signs the payload locally with your sr25519 keypair
  3. The signature is sent to bittensor_submit_signed → server submits the extrinsic

Your private key never leaves your process. The signer callback receives payload bytes; your keypair stays with you.

Installation

npm install @bittensormcp/sign

Usage

import { signAndSubmit } from '@bittensormcp/sign';
import { Keyring } from '@polkadot/keyring';

const keyring = new Keyring({ type: 'sr25519' });
const keypair = keyring.addFromMnemonic('your twelve word mnemonic ...');

const result = await signAndSubmit({
  endpoint: 'https://bittensormcp.com',
  token: walletJwt,           // from /api/auth/verify
  tool: 'bittensor_stake_add',
  args: {
    hotkey: '5G1YourHotkeyHere',
    amount: 0.01,
    netuid: 21,
  },
  signer: (payload) => keypair.sign(payload),
});

console.log('txHash:', result.txHash);

Supported tools

All 8 BittensorMCP write tools: bittensor_stake_add, bittensor_stake_remove, bittensor_stake_move, bittensor_transfer, bittensor_register, bittensor_serve_axon, bittensor_weights_set, bittensor_weights_commit.

Activating premium programmatically

Write tools require a premium subscription (0.1 TAO/month). Agents activate it without a browser:

import { activatePremium } from '@bittensormcp/sign';
const result = await activatePremium({ endpoint, token, signer: wallet.sign });
// → { subscriptionValidUntil, creditedDays, txHash }

Resuming a wallet across runs

import { walletFromMnemonic } from '@bittensormcp/sign';
const wallet = await walletFromMnemonic(savedMnemonic); // same shape as generateWallet()

Getting a wallet JWT

// 1. Get a challenge nonce
const { nonce } = await fetch(`${endpoint}/api/auth/challenge`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ ss58: keypair.address, domain: 'bittensormcp.com' }),
}).then(r => r.json());

// 2. Sign the challenge
const message = `bittensormcp-auth:${nonce}:bittensormcp.com`;
const signature = u8aToHex(keypair.sign(stringToU8a(message)));

// 3. Exchange for a JWT
const { token } = await fetch(`${endpoint}/api/auth/verify`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ ss58: keypair.address, nonce, signature }),
}).then(r => r.json());

Generating a wallet (no human-held keypair needed)

If your agent doesn't already have a coldkey, generate one locally — nothing leaves your process:

import { generateWallet, authenticate, signAndSubmit } from '@bittensormcp/sign';

const wallet = await generateWallet();
console.log(`Fund this address before writes: ${wallet.ss58}`);
// wallet.mnemonic is yours to store — this package never persists or sends it

const { token } = await authenticate({
  endpoint: 'https://bittensormcp.com',
  ss58: wallet.ss58,
  signer: wallet.sign,
});

const result = await signAndSubmit({
  endpoint: 'https://bittensormcp.com',
  token,
  tool: 'bittensor_stake_add',
  args: { hotkey: '5G1...', amount: 0.01, netuid: 21 },
  signer: wallet.sign,
});

Wallet generation and authentication are fully agentic — no human needs to touch a browser extension. Funding the address with TAO is the one step that always needs a value source outside the system; that's not a limitation of this package, it's what self-custody means.

Security

  • Zero postinstall scripts
  • @polkadot/util-crypto is the only runtime dependency, used solely by generateWallet() (lazy-imported — signAndSubmit/authenticate alone don't pull it in)
  • No network calls except to your configured endpoint
  • Your private key is never passed to this package — only the signer callback, and generateWallet()'s keypair never leaves the closure it's generated in