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

@bsv/ecpm-permission-module

v0.1.1

Published

BRC-98 ECPM semantic module for elliptic-curve point multiplication in BRC-100 wallets

Downloads

448

Readme

ECPM Permission Module

@bsv/ecpm-permission-module implements the BRC-229 p ecpm semantic module for BRC-100 wallets. It applies or removes a BRC-42/43-derived scalar to an arbitrary validated secp256k1 point without adding a method or wire call to the fixed BRC-100 interface.

Protocol

Applications call the existing getPublicKey method with:

p ecpm <apply|remove> <pointHex> <logicalProtocolID>

The logical protocol ID is 5–273 ASCII bytes. The complete dispatch envelope may be 353 bytes for apply or 354 bytes for remove; this preserves the full BRC-43 logical protocol namespace while remaining inside BRC-100's 400-byte protocol-string limit.

The security level remains in the normal BRC-43 tuple. The key ID, counterparty, privileged selection, privileged reason, and permission behavior remain in their existing getPublicKey fields.

const applied = await wallet.getPublicKey({
  protocolID: [2, `p ecpm apply ${pointHex} mental poker deal`],
  keyID: 'deck mask',
  counterparty: 'self'
})

const removed = await wallet.getPublicKey({
  protocolID: [2, `p ecpm remove ${applied.publicKey} mental poker deal`],
  keyID: 'deck mask',
  counterparty: 'self'
})

For both calls, the module derives the scalar under the canonical namespace p ecpm mental poker deal. The operation and point are deliberately excluded from the BRC-42 invoice so every point uses the same scalar and remove selects the inverse of the scalar used by apply.

Installation

Create the module with the wallet's ordinary KeyDeriverApi and an authorization callback, then register it under the ecpm scheme:

import { createEcpmModule } from '@bsv/ecpm-permission-module'
import { WalletPermissionsManager } from '@bsv/wallet-toolbox-client'

const ecpm = createEcpmModule({
  keyDeriver: setup.keyDeriver,
  authorize: async request => {
    return await showTrustedWalletPrompt({
      originator: request.originator,
      protocol: request.logicalProtocolID,
      counterparty: request.counterparty,
      privileged: request.privileged
    })
  },
  privilegedKeyDeriver: async reason => {
    return await acquirePrivilegedKeyDeriver(reason)
  }
})

const wallet = new WalletPermissionsManager(setup.wallet, adminOriginator, {
  permissionModules: { ecpm }
})

Call ecpm.dispose() when the host tears down the wallet. The method clears cached and pending authorization state.

Successful grants are capped at 1,024 entries with oldest-grant eviction, and at most 64 distinct authorization prompts may remain in flight. Requests that would exceed the pending limit fail closed until an existing prompt settles. These receiver-local bounds prevent a hostile application from turning a permanently pending authorization UI into unbounded wallet memory.

Security level 0 primary-key requests do not prompt. Levels 1 and 2 require the authorization callback, with level 2 grants scoped to the counterparty. Every privileged request requires authorization regardless of security level, and cached or in-flight privileged grants are scoped to the exact approved privilegedReason. Changing the reason requires a separate authorization. seekPermission: false fails unless an applicable grant is already cached.

Security model

The module:

  • accepts only getPublicKey in the p ecpm namespace, preventing the same derived key from being reused for signatures, HMACs, or BRC-2 encryption;
  • rejects identity-key and forSelf requests;
  • keeps the point and operation outside the derived-key identity;
  • isolates ordinary and privileged derivation providers;
  • checks the encoded x coordinate before parsing so a reducing parser cannot accept a non-canonical point;
  • accepts only finite, on-curve, lowercase compressed secp256k1 points; and
  • returns the existing { publicKey } result shape, so no BRC-100 wire change is required.

The module is trusted wallet code. Applications never receive a key deriver or private scalar. A privileged provider should acquire protected key material only after its reason has been displayed and authorized, and should retain it for no longer than the host wallet's existing privileged-key policy permits.

Verification

pnpm --filter @bsv/sdk build
pnpm --filter @bsv/wallet-toolbox-client build
pnpm --filter @bsv/ecpm-permission-module typecheck
pnpm --filter @bsv/ecpm-permission-module lint
pnpm --filter @bsv/ecpm-permission-module test:coverage
pnpm --filter @bsv/ecpm-permission-module test:property
pnpm --filter @bsv/ecpm-permission-module build
pnpm --filter @bsv/ecpm-permission-module pack:check

License

Open BSV License version 6. See LICENSE.txt.