Files
AtreidesAssetsFree/client/nostr/nip98.js
T
2026-10-29 11:57:29 +01:00

59 lines
2.4 KiB
JavaScript

// Generated, do not edit. sha256:f29f3a90c87550fd7890bda37eec12ad08ada3b62d0dc1ae18995512314d74ce
import { schnorr, sha256, bytesToHex, hexToBytes, utf8ToBytes } from '../vendor/crypto/noble-scure.js';
import { publicKeyOf } from './keys.js';
import { encrypt as nip44, decrypt as nip44Open, conversationKey } from './nip44.js';
const KIND = 27235;
export const eventId = (e) => bytesToHex(sha256(utf8ToBytes(JSON.stringify([0, e.pubkey, e.created_at, e.kind, e.tags, e.content]))));
export function nip98Event({ pubkey, url, method, body = '', now = Date.now() }) {
const tags = [['u', url], ['method', method]];
if (body) tags.push(['payload', bytesToHex(sha256(utf8ToBytes(body)))]);
return { pubkey, created_at: Math.floor(now / 1000), kind: KIND, tags, content: '' };
}
export function keySigner(secret) {
const pubkey = publicKeyOf(secret);
return {
kind: 'key',
pubkey,
async sign(event) {
const id = eventId(event);
return { ...event, id, sig: bytesToHex(schnorr.sign(hexToBytes(id), secret)) };
},
async nip44Encrypt(pubkey, text) {
return nip44(text, conversationKey(secret, pubkey));
},
async nip44Decrypt(pubkey, payload) {
return nip44Open(payload, conversationKey(secret, pubkey));
},
};
}
export async function extensionSigner(nostr = globalThis.nostr) {
if (!nostr || typeof nostr.getPublicKey !== 'function' || typeof nostr.signEvent !== 'function') {
throw new Error('No nostr extension (NIP-07) in this browser.');
}
const pubkey = String(await nostr.getPublicKey()).toLowerCase();
return {
kind: 'extension',
pubkey,
sign: (event) => nostr.signEvent(event),
nip44Encrypt: (to, text) => {
if (typeof nostr.nip44?.encrypt !== 'function') throw new Error('This nostr extension cannot encrypt with NIP-44.');
return nostr.nip44.encrypt(to, text);
},
nip44Decrypt: (from, payload) => {
if (typeof nostr.nip44?.decrypt !== 'function') throw new Error('This nostr extension cannot decrypt with NIP-44.');
return nostr.nip44.decrypt(from, payload);
},
};
}
export async function nip98Header(signer, { url, method, body = '', now = Date.now() }) {
const signed = await signer.sign(nip98Event({ pubkey: signer.pubkey, url, method, body, now }));
if (signed.pubkey !== signer.pubkey) throw new Error('The signer signed with another key than it gave.');
return `Nostr ${btoa(JSON.stringify(signed))}`;
}