helium.js is a miniature @noble/secp256k1: BIP-340 Schnorr keys, signing and verification in about 4kb of BigInt and crypto.subtle. Loaded alongside xenon.js, it signs nxe-publish events when no NIP-07 extension is present, and verifies incoming events under nhe-verify. It also runs in Deno and other runtimes with Web Crypto, where it needs no document.
<script src="helium.js"></script>
<script src="xenon.js"></script>
<form nxe-publish><input name="content"><button>Post</button></form>
<ol nxe-filter='{"kinds":[1]}' nhe-verify></ol>
The form publishes with a local key when there is no extension, and the list drops any event whose id or signature is invalid.
| attribute | description |
|---|---|
nhe-verify |
Verify every event for subscriptions on or under this element |
window.nheCfg = {local:true} always signs with the local key. window.nheCfg = {verify:true} verifies every subscription.
| function | returns |
|---|---|
helium.generate() |
new secret key (hex) |
helium.pub(sk) |
x-only public key (hex) |
helium.id(event) |
event id (hex) |
helium.finish(event, sk) |
signed event with pubkey, id, sig |
helium.check(event) |
true if id and signature are valid |
helium.sign(msg, sk, aux?) |
64-byte signature (Uint8Array) |
helium.verify(sig, msg, pk) |
true or false |
helium.key(sk?) |
local key: gets (creating one), sets, or with null replaces |
helium.signer |
NIP-07 shaped {getPublicKey, signEvent} using the local key |
BigInt arithmetic is not constant time, and the local key lives in localStorage. Use it for demos, throwaway or low-value keys. Prefer a NIP-07 extension for anything that matters. Tests check keys and signatures byte for byte against @noble/curves.
helium.js (3.8/1.6kb raw/brotli), prefix nhe-