Add NIP 55 signer support

This commit is contained in:
Chris Daley
2024-09-30 13:26:25 -07:00
committed by Jon Staab
parent 1ef7c1c59f
commit e1f8d6a4e0
6 changed files with 369 additions and 281 deletions
+4 -1
View File
@@ -3,7 +3,7 @@ import {ctx, memoize, omit, equals, assoc} from "@welshman/lib"
import {createEvent} from "@welshman/util"
import {withGetter, synced} from "@welshman/store"
import {type Nip46Handler} from "@welshman/signer"
import {Nip46Broker, Nip46Signer, Nip07Signer, Nip01Signer} from "@welshman/signer"
import {Nip46Broker, Nip46Signer, Nip07Signer, Nip01Signer, Nip55Signer} from "@welshman/signer"
export type Session = {
method: string
@@ -11,6 +11,7 @@ export type Session = {
token?: string
secret?: string
handler?: Nip46Handler
signer?: string
}
export const pubkey = withGetter(synced<string | null>("pubkey", null))
@@ -50,6 +51,8 @@ export const getSigner = memoize((session: Session) => {
return new Nip01Signer(session.secret!)
case "nip46":
return new Nip46Signer(Nip46Broker.get(session.pubkey, session.secret!, session.handler!))
case "nip55":
return new Nip55Signer(session.signer!)
default:
return null
}
+3
View File
@@ -35,5 +35,8 @@
"@welshman/net": "0.0.22",
"@welshman/util": "0.0.33",
"nostr-tools": "^2.7.2"
},
"peerDependencies": {
"nostr-signer-capacitor-plugin": "github:chebizarro/nostr-signer-capacitor-plugin"
}
}
+1
View File
@@ -3,3 +3,4 @@ export * from './nip59'
export * from './signers/nip01'
export * from './signers/nip07'
export * from './signers/nip46'
export * from './signers/nip55'
+143
View File
@@ -0,0 +1,143 @@
import {SignedEvent, StampedEvent} from "@welshman/util"
import {hash, own, ISigner} from "../util"
import {NostrSignerPlugin, AppInfo} from "nostr-signer-capacitor-plugin"
import {nip19} from "nostr-tools"
export const getNip55 = async (): Promise<AppInfo[]> => {
const {apps} = await NostrSignerPlugin.getInstalledSignerApps()
return apps
}
export class Nip55Signer implements ISigner {
#lock = Promise.resolve()
#plugin = NostrSignerPlugin
#packageName: string
#packageNameSet = false
#npub?: string
#publicKey?: string
constructor(packageName: string) {
this.#packageName = packageName
this.#initialize()
}
async #initialize() {
if (!this.#packageNameSet) {
await this.#plugin.setPackageName({packageName: this.#packageName})
this.#packageNameSet = true
}
}
#then = async <T>(f: (signer: typeof NostrSignerPlugin) => T | Promise<T>): Promise<T> => {
const promise = this.#lock.then(async () => {
if (!this.#packageNameSet) {
try {
await this.#plugin.setPackageName({packageName: this.#packageName})
this.#packageNameSet = true
} catch (error) {
this.#packageNameSet = false
throw error
}
}
return f(this.#plugin)
})
this.#lock = promise.then(() => Promise.resolve())
return promise
}
getPubkey = async (): Promise<string> => {
return this.#then(async signer => {
if (!this.#publicKey || !this.#npub) {
try {
const {npub} = await signer.getPublicKey()
this.#npub = npub
const {data} = nip19.decode(npub)
this.#publicKey = data as string
} catch (error) {
throw new Error(`Failed to get public key`)
}
}
return this.#publicKey
})
}
sign = async (template: StampedEvent): Promise<SignedEvent> => {
const pubkey = await this.getPubkey() // hex-encoded public key
const npub = this.#npub! // Bech32-encoded public key
const event = {sig: "", ...hash(own(template, pubkey))}
return this.#then(async signer => {
const {event: signedEventJson} = await signer.signEvent({
eventJson: JSON.stringify(event),
eventId: event.id,
npub: npub,
})
const signedEvent = JSON.parse(signedEventJson) as SignedEvent
return signedEvent
})
}
nip04 = {
encrypt: async (recipientPubKey: string, message: string): Promise<string> => {
const myNpub = this.#npub
if (!myNpub) {
await this.getPubkey()
}
return this.#then(async signer => {
const {result} = await signer.nip04Encrypt({
pubKey: recipientPubKey,
plainText: message,
npub: this.#npub!,
})
return result
})
},
decrypt: async (senderPubKey: string, message: string): Promise<string> => {
const myNpub = this.#npub
if (!myNpub) {
await this.getPubkey()
}
return this.#then(async signer => {
const {result} = await signer.nip04Decrypt({
pubKey: senderPubKey,
encryptedText: message,
npub: this.#npub!,
})
return result
})
},
}
nip44 = {
encrypt: async (recipientPubKey: string, message: string): Promise<string> => {
const myNpub = this.#npub
if (!myNpub) {
await this.getPubkey()
}
return this.#then(async signer => {
const {result} = await signer.nip44Encrypt({
pubKey: recipientPubKey,
plainText: message,
npub: this.#npub!,
})
return result
})
},
decrypt: async (senderPubKey: string, message: string): Promise<string> => {
const myNpub = this.#npub
if (!myNpub) {
await this.getPubkey()
}
return this.#then(async signer => {
const {result} = await signer.nip44Decrypt({
pubKey: senderPubKey,
encryptedText: message,
npub: this.#npub!,
})
return result
})
},
}
}