From 09e687ab0528e25d63c9280547938e499bf24da8 Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Tue, 13 Jan 2026 10:25:29 -0800 Subject: [PATCH] Remove promenade and pomade stuff from signer package --- package.json | 2 +- packages/app/package.json | 3 +- packages/app/src/session.ts | 81 +++++++++++++- packages/content/package.json | 2 +- packages/editor/package.json | 2 +- packages/feeds/package.json | 2 +- packages/lib/package.json | 2 +- packages/net/package.json | 2 +- packages/router/package.json | 2 +- packages/signer/package.json | 7 +- packages/signer/src/index.ts | 1 - packages/signer/src/signers/nip46.ts | 145 +------------------------- packages/signer/src/signers/pomade.ts | 68 ------------ packages/store/package.json | 2 +- packages/util/package.json | 2 +- pnpm-lock.yaml | 37 +------ 16 files changed, 92 insertions(+), 268 deletions(-) delete mode 100644 packages/signer/src/signers/pomade.ts diff --git a/package.json b/package.json index 97225d5..f0f4a6a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@welshman", "private": true, - "version": "0.7.1", + "version": "0.8.0-pre.1", "workspaces": [ "packages/*" ], diff --git a/packages/app/package.json b/packages/app/package.json index 8984b3f..0a17ea5 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@welshman/app", - "version": "0.7.1", + "version": "0.8.0-pre.1", "author": "hodlbod", "license": "MIT", "description": "A collection of svelte stores for use in building nostr client applications.", @@ -32,6 +32,7 @@ "@welshman/signer": "workspace:*", "@welshman/store": "workspace:*", "@welshman/util": "workspace:*", + "nostr-tools": "^2.19.4", "svelte": "^4.2.18" }, "devDependencies": { diff --git a/packages/app/src/session.ts b/packages/app/src/session.ts index a166213..e9d6586 100644 --- a/packages/app/src/session.ts +++ b/packages/app/src/session.ts @@ -1,6 +1,7 @@ +import * as nt44 from "nostr-tools/nip44" import {Client, ClientOptions} from "@pomade/core" import {derived, writable} from "svelte/store" -import {cached, randomId, append, omit, equals, assoc} from "@welshman/lib" +import {cached, randomId, append, omit, equals, assoc, thrower, hexToBytes} from "@welshman/lib" import {withGetter} from "@welshman/store" import { Wallet, @@ -14,17 +15,81 @@ import { import { Nip59, WrappedSigner, - PomadeSigner, Nip46Broker, Nip46Signer, Nip07Signer, Nip01Signer, Nip55Signer, ISigner, + SignOptions, + signWithOptions, } from "@welshman/signer" import {WrapManager} from "@welshman/net" import {tracker, repository} from "./core.js" +class PomadeSigner implements ISigner { + #pubkey: string + #sharedSecretCache = new Map>() + + constructor(readonly client: Client) { + this.#pubkey = client.userPubkey + } + + private getSharedSecret = async (pubkey: string) => { + let sharedSecret = this.#sharedSecretCache.get(pubkey) + if (!sharedSecret) { + const hexSharedSecret = await this.client.getConversationKey(pubkey) + + if (hexSharedSecret) { + sharedSecret = hexToBytes(hexSharedSecret) + this.#sharedSecretCache.set(pubkey, sharedSecret) + } + } + + return sharedSecret + } + + getPubkey = async () => this.#pubkey + + sign = (event: StampedEvent, options: SignOptions = {}) => { + const promise = this.client.sign(event).then(r => { + if (!r.event) { + throw new Error(r.messages[0]?.payload.message || "Failed to sign event") + } + + return r.event + }) + + return signWithOptions(promise, options) + } + + nip04 = { + encrypt: thrower("PomadeSigner does not support nip44"), + decrypt: thrower("PomadeSigner does not support nip44"), + } + + nip44 = { + encrypt: async (pubkey: string, message: string) => { + const sharedSecret = await this.getSharedSecret(pubkey) + + if (!sharedSecret) { + throw new Error("Failed to get shared secret") + } + + return nt44.v2.encrypt(message, sharedSecret) + }, + decrypt: async (pubkey: string, message: string) => { + const sharedSecret = await this.getSharedSecret(pubkey) + + if (!sharedSecret) { + throw new Error("Failed to get shared secret") + } + + return nt44.v2.decrypt(message, sharedSecret) + }, + } +} + export enum SessionMethod { Nip01 = "nip01", Nip07 = "nip07", @@ -66,6 +131,7 @@ export type SessionPomade = { method: SessionMethod.Pomade pubkey: string clientOptions: ClientOptions + email: string } export type SessionPubkey = { @@ -164,10 +230,15 @@ export const makeNip55Session = (pubkey: string, signer: string): SessionNip55 = signer, }) -export const makePomadeSession = (pubkey: string, clientOptions: ClientOptions): SessionPomade => ({ +export const makePomadeSession = ( + pubkey: string, + email: string, + clientOptions: ClientOptions, +): SessionPomade => ({ method: SessionMethod.Pomade, pubkey, clientOptions, + email, }) export const makePubkeySession = (pubkey: string): SessionPubkey => ({ @@ -211,8 +282,8 @@ export const loginWithNip46 = ( export const loginWithNip55 = (pubkey: string, signer: string) => addSession(makeNip55Session(pubkey, signer)) -export const loginWithPomade = (pubkey: string, clientOptions: ClientOptions) => - addSession(makePomadeSession(pubkey, clientOptions)) +export const loginWithPomade = (pubkey: string, email: string, clientOptions: ClientOptions) => + addSession(makePomadeSession(pubkey, email, clientOptions)) export const loginWithPubkey = (pubkey: string) => addSession(makePubkeySession(pubkey)) diff --git a/packages/content/package.json b/packages/content/package.json index bbd7f72..a04d78b 100644 --- a/packages/content/package.json +++ b/packages/content/package.json @@ -1,6 +1,6 @@ { "name": "@welshman/content", - "version": "0.7.1", + "version": "0.8.0-pre.1", "author": "hodlbod", "license": "MIT", "description": "A collection of utilities for parsing nostr note content.", diff --git a/packages/editor/package.json b/packages/editor/package.json index 1803bfd..8a4e43f 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@welshman/editor", - "version": "0.7.1", + "version": "0.8.0-pre.1", "author": "hodlbod", "license": "MIT", "description": "A batteries-included nostr editor.", diff --git a/packages/feeds/package.json b/packages/feeds/package.json index ef4b19a..f317de5 100644 --- a/packages/feeds/package.json +++ b/packages/feeds/package.json @@ -1,6 +1,6 @@ { "name": "@welshman/feeds", - "version": "0.7.1", + "version": "0.8.0-pre.1", "author": "hodlbod", "license": "MIT", "description": "Utilities for building dynamic nostr feeds.", diff --git a/packages/lib/package.json b/packages/lib/package.json index 73bc24e..c7a767d 100644 --- a/packages/lib/package.json +++ b/packages/lib/package.json @@ -1,6 +1,6 @@ { "name": "@welshman/lib", - "version": "0.7.1", + "version": "0.8.0-pre.1", "author": "hodlbod", "license": "MIT", "description": "A collection of utilities.", diff --git a/packages/net/package.json b/packages/net/package.json index ed4c339..b103431 100644 --- a/packages/net/package.json +++ b/packages/net/package.json @@ -1,6 +1,6 @@ { "name": "@welshman/net", - "version": "0.7.1", + "version": "0.8.0-pre.1", "author": "hodlbod", "license": "MIT", "description": "Utilities for connecting with nostr relays.", diff --git a/packages/router/package.json b/packages/router/package.json index 238a020..c60e985 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@welshman/router", - "version": "0.7.1", + "version": "0.8.0-pre.1", "author": "hodlbod", "license": "MIT", "description": "A collection of utilities for nostr relay selection.", diff --git a/packages/signer/package.json b/packages/signer/package.json index 6cf6f9a..d36a7c6 100644 --- a/packages/signer/package.json +++ b/packages/signer/package.json @@ -1,6 +1,6 @@ { "name": "@welshman/signer", - "version": "0.7.1", + "version": "0.8.0-pre.1", "author": "hodlbod", "license": "MIT", "description": "A nostr signer implemenation supporting several login methods.", @@ -19,13 +19,9 @@ "compile": "tsc -b tsconfig.build.json", "prepublishOnly": "pnpm run build" }, - "dependencies": { - "@jsr/fiatjaf__promenade-trusted-dealer": "^0.4.1" - }, "peerDependencies": { "@noble/curves": "^1.9.7", "@noble/hashes": "^2.0.1", - "@pomade/core": "^0.0.5", "@welshman/lib": "workspace:*", "@welshman/net": "workspace:*", "@welshman/util": "workspace:*", @@ -36,7 +32,6 @@ "@capacitor/core": "^7.2.0", "@noble/curves": "^1.9.7", "@noble/hashes": "^2.0.1", - "@pomade/core": "^0.0.5", "@welshman/lib": "workspace:*", "@welshman/net": "workspace:*", "@welshman/util": "workspace:*", diff --git a/packages/signer/src/index.ts b/packages/signer/src/index.ts index a4a9dd6..8a22420 100644 --- a/packages/signer/src/index.ts +++ b/packages/signer/src/index.ts @@ -4,4 +4,3 @@ export * from "./signers/nip01.js" export * from "./signers/nip07.js" export * from "./signers/nip46.js" export * from "./signers/nip55.js" -export * from "./signers/pomade.js" diff --git a/packages/signer/src/signers/nip46.ts b/packages/signer/src/signers/nip46.ts index 0baf240..52c069f 100644 --- a/packages/signer/src/signers/nip46.ts +++ b/packages/signer/src/signers/nip46.ts @@ -1,14 +1,5 @@ -import { - trustedKeyDeal, - hexShard, - hexPubShard, - KeyShard, -} from "@jsr/fiatjaf__promenade-trusted-dealer" import { Emitter, - uniq, - spec, - inc, throttle, makePromise, defer, @@ -16,24 +7,19 @@ import { tryCatch, randomId, MaybeAsync, - shuffle, } from "@welshman/lib" import { - getPubkey, HashedEvent, makeEvent, makeSecret, normalizeRelayUrl, NOSTR_CONNECT, prep, - PROMENADE_REGISTER_ACCOUNT, - PROMENADE_SHARD_ACK, - PROMENADE_SHARD_SHARE, RelayMode, StampedEvent, TrustedEvent, } from "@welshman/util" -import {publish, request, PublishStatus, AdapterContext} from "@welshman/net" +import {publish, request, AdapterContext} from "@welshman/net" import {ISigner, EncryptionImplementation, signWithOptions, SignOptions, decrypt} from "../util.js" import {Nip01Signer} from "./nip01.js" @@ -346,135 +332,6 @@ export class Nip46Broker extends Emitter { }) } - static fromPromenade = async (options: PromenadeOptions) => { - const [m, n] = options.policy - - if (options.signerPubkeys.length < n) { - throw new Error("Not enough signers to create all shards") - } - - const deal = trustedKeyDeal(BigInt("0x" + options.secret), m, n) - const signer = Nip01Signer.fromSecret(options.secret) - const ourPubkey = await signer.getPubkey() - const ackRelays = await options.getPubkeyRelays(ourPubkey, RelayMode.Read) - const remainingSignerPubkeys = shuffle(uniq(options.signerPubkeys)) - const errorsBySignerPubkey = new Map() - const shardsBySignerPubkey = new Map() - - if (ackRelays.length === 0) { - throw new Error("No read relays returned for user pubkey") - } - - nip46Log(`generated promenade shards for user ${ourPubkey}`, deal) - - await Promise.all( - deal.shards.map(async (shard, i) => { - while (remainingSignerPubkeys.length > 0) { - const signerPubkey = remainingSignerPubkeys.shift()! - - nip46Log(`generating proof of work for shard ${i}`) - - const shardTemplate = makeEvent(PROMENADE_SHARD_SHARE, { - content: await signer.nip44.encrypt(signerPubkey, hexShard(shard)), - tags: [ - ["p", signerPubkey], - ["coordinator", options.coordinatorUrl], - ...ackRelays.map(url => ["reply", url]), - ], - }) - - const shardTemplateWithWork = await tryCatch(() => - options.generatePow(prep(shardTemplate, ourPubkey), 20), - ) - - if (!shardTemplateWithWork) { - errorsBySignerPubkey.set(signerPubkey, "Failed to generate work") - continue - } - - const shardEvent = await signer.sign(shardTemplateWithWork) - const shardRelays = await options.getPubkeyRelays(signerPubkey, RelayMode.Read) - const publishResults = await publish({relays: shardRelays, event: shardEvent}) - - nip46Log(`published shard ${i} to signer ${signerPubkey}`, shardRelays, publishResults) - - if (!Object.values(publishResults).some(spec({status: PublishStatus.Success}))) { - errorsBySignerPubkey.set(signerPubkey, "Failed to publish shard") - continue - } - - const controller = new AbortController() - const signal = AbortSignal.any([controller.signal, AbortSignal.timeout(30_000)]) - - await request({ - signal, - relays: ackRelays, - filters: [ - { - kinds: [PROMENADE_SHARD_ACK], - authors: [signerPubkey], - "#p": [ourPubkey], - "#e": [shardEvent.id], - }, - ], - onEvent: (event: TrustedEvent, url: string) => { - nip46Log(`received ack for shard ${i} from signer ${signerPubkey} on ${url}`) - shardsBySignerPubkey.set(signerPubkey, shard) - options.onProgress?.(shardsBySignerPubkey.size / inc(n)) - controller.abort() - }, - }) - - if (shardsBySignerPubkey.has(signerPubkey)) { - break - } else { - errorsBySignerPubkey.set(signerPubkey, "Failed to receive shard ACK") - nip46Log(`failed to receive ack for shard ${i} from signer ${signerPubkey}`) - } - } - }), - ) - - if (shardsBySignerPubkey.size < deal.shards.length) { - throw new PromenadeShardError("Failed to publish all shards", errorsBySignerPubkey) - } - - const connectSecret = randomId() - const signerSecret = makeSecret() - const signerPubkey = getPubkey(signerSecret) - const tags = [ - ["h", signerPubkey], - ["threshold", String(m)], - ["handlersecret", signerSecret], - ["profile", "MAIN", connectSecret, ""], - ] - - for (const [pubkey, shard] of shardsBySignerPubkey) { - tags.push(["p", pubkey, hexPubShard(shard.pubShard)]) - } - - nip46Log(`registering coordinator account`, tags) - - const relays = [options.coordinatorUrl] - const event = await signer.sign(makeEvent(PROMENADE_REGISTER_ACCOUNT, {tags})) - const accountResults = await publish({relays, event}) - - if (!Object.values(accountResults).some(spec({status: PublishStatus.Success}))) { - throw new Error("Failed to publish accounts to coordinator") - } - - nip46Log(`successfully created promenade broker`) - - const clientSecret = makeSecret() - - return new Nip46Broker({ - relays, - clientSecret, - signerPubkey, - connectSecret, - }) - } - // Getters for helper objects makeSigner = () => new Nip01Signer(this.params.clientSecret) diff --git a/packages/signer/src/signers/pomade.ts b/packages/signer/src/signers/pomade.ts deleted file mode 100644 index bc1e61c..0000000 --- a/packages/signer/src/signers/pomade.ts +++ /dev/null @@ -1,68 +0,0 @@ -import * as nt44 from "nostr-tools/nip44" -import type {Client} from "@pomade/core" -import type {StampedEvent} from "@welshman/util" -import {thrower, hexToBytes} from "@welshman/lib" -import {ISigner, SignOptions, signWithOptions} from "../util.js" - -export class PomadeSigner implements ISigner { - #pubkey: string - #sharedSecretCache = new Map>() - - constructor(readonly client: Client) { - this.#pubkey = client.userPubkey - } - - private getSharedSecret = async (pubkey: string) => { - let sharedSecret = this.#sharedSecretCache.get(pubkey) - if (!sharedSecret) { - const hexSharedSecret = await this.client.getConversationKey(pubkey) - - if (hexSharedSecret) { - sharedSecret = hexToBytes(hexSharedSecret) - this.#sharedSecretCache.set(pubkey, sharedSecret) - } - } - - return sharedSecret - } - - getPubkey = async () => this.#pubkey - - sign = (event: StampedEvent, options: SignOptions = {}) => { - const promise = this.client.sign(event).then(r => { - if (!r.event) { - throw new Error(r.messages[0]?.payload.message || "Failed to sign event") - } - - return r.event - }) - - return signWithOptions(promise, options) - } - - nip04 = { - encrypt: thrower("PomadeSigner does not support nip44"), - decrypt: thrower("PomadeSigner does not support nip44"), - } - - nip44 = { - encrypt: async (pubkey: string, message: string) => { - const sharedSecret = await this.getSharedSecret(pubkey) - - if (!sharedSecret) { - throw new Error("Failed to get shared secret") - } - - return nt44.v2.encrypt(message, sharedSecret) - }, - decrypt: async (pubkey: string, message: string) => { - const sharedSecret = await this.getSharedSecret(pubkey) - - if (!sharedSecret) { - throw new Error("Failed to get shared secret") - } - - return nt44.v2.decrypt(message, sharedSecret) - }, - } -} diff --git a/packages/store/package.json b/packages/store/package.json index 7c0ad85..7de35c7 100644 --- a/packages/store/package.json +++ b/packages/store/package.json @@ -1,6 +1,6 @@ { "name": "@welshman/store", - "version": "0.7.1", + "version": "0.8.0-pre.1", "author": "hodlbod", "license": "MIT", "description": "A collection of utilities based on svelte/store for use with welshman", diff --git a/packages/util/package.json b/packages/util/package.json index f965666..4e69004 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@welshman/util", - "version": "0.7.1", + "version": "0.8.0-pre.1", "author": "hodlbod", "license": "MIT", "description": "A collection of nostr-related utilities.", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 33ba889..9c12499 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -175,6 +175,9 @@ importers: fuse.js: specifier: ^7.0.0 version: 7.1.0 + nostr-tools: + specifier: ^2.19.4 + version: 2.19.4(typescript@5.8.2) throttle-debounce: specifier: ^5.0.2 version: 5.0.2 @@ -384,10 +387,6 @@ importers: version: 5.8.2 packages/signer: - dependencies: - '@jsr/fiatjaf__promenade-trusted-dealer': - specifier: ^0.4.1 - version: 0.4.1 devDependencies: '@capacitor/core': specifier: ^7.2.0 @@ -398,9 +397,6 @@ importers: '@noble/hashes': specifier: ^2.0.1 version: 2.0.1 - '@pomade/core': - specifier: ^0.0.5 - version: 0.0.5(typescript@5.8.2)(ws@8.18.1) '@welshman/lib': specifier: workspace:* version: link:../lib @@ -868,15 +864,6 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@jsr/fiatjaf__promenade-trusted-dealer@0.4.1': - resolution: {integrity: sha512-K9WjpDkQGyLl5gUZBLr3Gb+b5b1r8miZmDOo4+ZlzGQgoXD2TaqT+dkBjL/yLj/pYwBcd1Bschv0xuNpguL2ZQ==, tarball: https://npm.jsr.io/~/11/@jsr/fiatjaf__promenade-trusted-dealer/0.4.1.tgz} - - '@jsr/henrygd__semaphore@0.0.2': - resolution: {integrity: sha512-nrwZ8HaqU1Agb2ij8omIxaOCAsKkDHWcwS9hTRumPhZuptwh6/0BJExBd8+eClTYM7jBnZxK+cP4WJRTcHBvCA==, tarball: https://npm.jsr.io/~/11/@jsr/henrygd__semaphore/0.0.2.tgz} - - '@jsr/nostr__tools@2.16.2': - resolution: {integrity: sha512-QK1XwHvAnqEwbimD+ywbLQ3T2iI+/qE/zrRgOhmtjoEGlCWgtbPTNJ6Y/MEunXr6H/MnuHV+s400i/Yk4suvGQ==, tarball: https://npm.jsr.io/~/11/@jsr/nostr__tools/2.16.2.tgz} - '@microsoft/api-extractor-model@7.32.1': resolution: {integrity: sha512-u4yJytMYiUAnhcNQcZDTh/tVtlrzKlyKrQnLOV+4Qr/5gV+cpufWzCYAB1Q23URFqD6z2RoL2UYncM9xJVGNKA==} @@ -3632,24 +3619,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@jsr/fiatjaf__promenade-trusted-dealer@0.4.1': - dependencies: - '@jsr/henrygd__semaphore': 0.0.2 - '@jsr/nostr__tools': 2.16.2 - '@noble/curves': 1.9.7 - - '@jsr/henrygd__semaphore@0.0.2': {} - - '@jsr/nostr__tools@2.16.2': - dependencies: - '@noble/ciphers': 0.5.3 - '@noble/curves': 1.2.0 - '@noble/hashes': 1.3.1 - '@scure/base': 1.1.1 - '@scure/bip32': 1.3.1 - '@scure/bip39': 1.2.1 - nostr-wasm: 0.1.0 - '@microsoft/api-extractor-model@7.32.1(@types/node@22.13.17)': dependencies: '@microsoft/tsdoc': 0.16.0