Remove nip46 broker getter, since websocket connections were getting closed and interrupting login flows
This commit is contained in:
+42
-23
@@ -1,5 +1,5 @@
|
|||||||
import {derived} from "svelte/store"
|
import {derived} from "svelte/store"
|
||||||
import {cached, hash, omit, equals, assoc} from "@welshman/lib"
|
import {cached, omit, equals, assoc} from "@welshman/lib"
|
||||||
import {withGetter, synced} from "@welshman/store"
|
import {withGetter, synced} from "@welshman/store"
|
||||||
import {
|
import {
|
||||||
Nip46Broker,
|
Nip46Broker,
|
||||||
@@ -64,7 +64,7 @@ export const pubkey = withGetter(synced<string | undefined>("pubkey", undefined)
|
|||||||
export const sessions = withGetter(synced<Record<string, Session>>("sessions", {}))
|
export const sessions = withGetter(synced<Record<string, Session>>("sessions", {}))
|
||||||
|
|
||||||
export const session = withGetter(
|
export const session = withGetter(
|
||||||
derived([pubkey, sessions], ([$pubkey, $sessions]) => ($pubkey ? $sessions[$pubkey] : null)),
|
derived([pubkey, sessions], ([$pubkey, $sessions]) => ($pubkey ? $sessions[$pubkey] : undefined)),
|
||||||
)
|
)
|
||||||
|
|
||||||
export const getSession = (pubkey: string) => sessions.get()[pubkey]
|
export const getSession = (pubkey: string) => sessions.get()[pubkey]
|
||||||
@@ -84,13 +84,20 @@ export const updateSession = (pubkey: string, f: (session: Session) => Session)
|
|||||||
putSession(f(getSession(pubkey)))
|
putSession(f(getSession(pubkey)))
|
||||||
|
|
||||||
export const dropSession = (_pubkey: string) => {
|
export const dropSession = (_pubkey: string) => {
|
||||||
|
const $signer = getSigner.pop(getSession(_pubkey))
|
||||||
|
|
||||||
|
if ($signer instanceof Nip46Signer) {
|
||||||
|
$signer.broker.cleanup()
|
||||||
|
}
|
||||||
|
|
||||||
pubkey.update($pubkey => ($pubkey === _pubkey ? undefined : $pubkey))
|
pubkey.update($pubkey => ($pubkey === _pubkey ? undefined : $pubkey))
|
||||||
sessions.update($sessions => omit([_pubkey], $sessions))
|
sessions.update($sessions => omit([_pubkey], $sessions))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const clearSessions = () => {
|
export const clearSessions = () => {
|
||||||
pubkey.set(undefined)
|
for (const pubkey of Object.keys(sessions.get())) {
|
||||||
sessions.set({})
|
dropSession(pubkey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Session factories
|
// Session factories
|
||||||
@@ -129,6 +136,23 @@ export const makePubkeySession = (pubkey: string): SessionPubkey => ({
|
|||||||
pubkey,
|
pubkey,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Type guards
|
||||||
|
|
||||||
|
export const isNip01Session = (session?: Session): session is SessionNip01 =>
|
||||||
|
session?.method === SessionMethod.Nip01
|
||||||
|
|
||||||
|
export const isNip07Session = (session?: Session): session is SessionNip07 =>
|
||||||
|
session?.method === SessionMethod.Nip07
|
||||||
|
|
||||||
|
export const isNip46Session = (session?: Session): session is SessionNip46 =>
|
||||||
|
session?.method === SessionMethod.Nip46
|
||||||
|
|
||||||
|
export const isNip55Session = (session?: Session): session is SessionNip55 =>
|
||||||
|
session?.method === SessionMethod.Nip55
|
||||||
|
|
||||||
|
export const isPubkeySession = (session?: Session): session is SessionPubkey =>
|
||||||
|
session?.method === SessionMethod.Pubkey
|
||||||
|
|
||||||
// Login utilities
|
// Login utilities
|
||||||
|
|
||||||
export const loginWithNip01 = (secret: string) => addSession(makeNip01Session(secret))
|
export const loginWithNip01 = (secret: string) => addSession(makeNip01Session(secret))
|
||||||
@@ -153,25 +177,20 @@ export const nip46Perms = "sign_event:22242,nip04_encrypt,nip04_decrypt,nip44_en
|
|||||||
|
|
||||||
export const getSigner = cached({
|
export const getSigner = cached({
|
||||||
maxSize: 100,
|
maxSize: 100,
|
||||||
getKey: ([session]: [Session | null]) => hash(String(JSON.stringify(session))),
|
getKey: ([session]: [Session | undefined]) => `${session?.method}:${session?.pubkey}`,
|
||||||
getValue: ([session]: [Session | null]) => {
|
getValue: ([session]: [Session | undefined]) => {
|
||||||
switch (session?.method) {
|
if (isNip07Session(session)) return new Nip07Signer()
|
||||||
case "nip07":
|
if (isNip01Session(session)) return new Nip01Signer(session.secret)
|
||||||
return new Nip07Signer()
|
if (isNip55Session(session)) return new Nip55Signer(session.signer)
|
||||||
case "nip01":
|
if (isNip46Session(session)) {
|
||||||
return new Nip01Signer(session.secret!)
|
const {
|
||||||
case "nip46":
|
secret: clientSecret,
|
||||||
return new Nip46Signer(
|
handler: {relays, pubkey: signerPubkey},
|
||||||
Nip46Broker.get({
|
} = session
|
||||||
clientSecret: session.secret!,
|
const broker = new Nip46Broker({clientSecret, signerPubkey, relays})
|
||||||
relays: session.handler!.relays,
|
const signer = new Nip46Signer(broker)
|
||||||
signerPubkey: session.handler!.pubkey,
|
|
||||||
}),
|
return signer
|
||||||
)
|
|
||||||
case "nip55":
|
|
||||||
return new Nip55Signer(session.signer!)
|
|
||||||
default:
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -35,6 +35,14 @@ export class LRUCache<T, U> {
|
|||||||
this.map.delete(this.keys.shift() as T)
|
this.map.delete(this.keys.shift() as T)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pop(k: T) {
|
||||||
|
const v = this.get(k)
|
||||||
|
|
||||||
|
this.map.delete(k)
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,9 +72,16 @@ export function cached<T, V, Args extends any[]>({
|
|||||||
return cache.get(k)!
|
return cache.get(k)!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const pop = (...args: Args) => {
|
||||||
|
const k = getKey(args)
|
||||||
|
|
||||||
|
return cache.has(k) ? cache.pop(k)! : getValue(args)
|
||||||
|
}
|
||||||
|
|
||||||
get.cache = cache
|
get.cache = cache
|
||||||
get.getKey = getKey
|
get.getKey = getKey
|
||||||
get.getValue = getValue
|
get.getValue = getValue
|
||||||
|
get.pop = pop
|
||||||
|
|
||||||
return get
|
return get
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@welshman/signer",
|
"name": "@welshman/signer",
|
||||||
"version": "0.2.2",
|
"version": "0.2.3",
|
||||||
"author": "hodlbod",
|
"author": "hodlbod",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "A nostr signer implemenation supporting several login methods.",
|
"description": "A nostr signer implemenation supporting several login methods.",
|
||||||
|
|||||||
@@ -1,13 +1,4 @@
|
|||||||
import {
|
import {Emitter, throttle, makePromise, defer, sleep, tryCatch, randomId} from "@welshman/lib"
|
||||||
Emitter,
|
|
||||||
throttle,
|
|
||||||
makePromise,
|
|
||||||
defer,
|
|
||||||
sleep,
|
|
||||||
tryCatch,
|
|
||||||
randomId,
|
|
||||||
equals,
|
|
||||||
} from "@welshman/lib"
|
|
||||||
import {
|
import {
|
||||||
createEvent,
|
createEvent,
|
||||||
normalizeRelayUrl,
|
normalizeRelayUrl,
|
||||||
@@ -19,6 +10,14 @@ import {publish, request, AdapterContext} from "@welshman/net"
|
|||||||
import {ISigner, EncryptionImplementation, decrypt, hash, own} from "../util.js"
|
import {ISigner, EncryptionImplementation, decrypt, hash, own} from "../util.js"
|
||||||
import {Nip01Signer} from "./nip01.js"
|
import {Nip01Signer} from "./nip01.js"
|
||||||
|
|
||||||
|
export type Nip46Context = {
|
||||||
|
debug: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const nip46Context = {
|
||||||
|
debug: false,
|
||||||
|
}
|
||||||
|
|
||||||
export type Nip46Algorithm = "nip04" | "nip44"
|
export type Nip46Algorithm = "nip04" | "nip44"
|
||||||
|
|
||||||
export enum Nip46Event {
|
export enum Nip46Event {
|
||||||
@@ -33,7 +32,6 @@ export type Nip46BrokerParams = {
|
|||||||
signerPubkey?: string
|
signerPubkey?: string
|
||||||
algorithm?: Nip46Algorithm
|
algorithm?: Nip46Algorithm
|
||||||
context?: AdapterContext
|
context?: AdapterContext
|
||||||
debug?: (message: string, ...args: any[]) => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Nip46Response = {
|
export type Nip46Response = {
|
||||||
@@ -58,8 +56,6 @@ export type Nip46ResponseWithError = {
|
|||||||
error: string
|
error: string
|
||||||
}
|
}
|
||||||
|
|
||||||
let singleton: Nip46Broker
|
|
||||||
|
|
||||||
const popupManager = (() => {
|
const popupManager = (() => {
|
||||||
let pendingUrl = ""
|
let pendingUrl = ""
|
||||||
let pendingSince = 0
|
let pendingSince = 0
|
||||||
@@ -190,7 +186,9 @@ export class Nip46Sender extends Emitter {
|
|||||||
try {
|
try {
|
||||||
await this.send(request)
|
await this.send(request)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
this.params.debug?.("nip46 error:", error, request)
|
if (nip46Context.debug) {
|
||||||
|
console.log("nip46 error:", error, request)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -263,17 +261,6 @@ export class Nip46Broker extends Emitter {
|
|||||||
this.receiver = this.makeReceiver()
|
this.receiver = this.makeReceiver()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use a static getter to avoid duplicate connections
|
|
||||||
|
|
||||||
static get(params: Nip46BrokerParams) {
|
|
||||||
if (!singleton?.hasParams(params)) {
|
|
||||||
singleton?.teardown()
|
|
||||||
singleton = new Nip46Broker(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
return singleton
|
|
||||||
}
|
|
||||||
|
|
||||||
// Static utility methods
|
// Static utility methods
|
||||||
|
|
||||||
static parseBunkerUrl = (url: string) => {
|
static parseBunkerUrl = (url: string) => {
|
||||||
@@ -294,12 +281,6 @@ export class Nip46Broker extends Emitter {
|
|||||||
return {signerPubkey, connectSecret, relays: relays.map(normalizeRelayUrl)}
|
return {signerPubkey, connectSecret, relays: relays.map(normalizeRelayUrl)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expose params without exposing params
|
|
||||||
|
|
||||||
hasParams(params: Nip46BrokerParams) {
|
|
||||||
return equals(this.params, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Getters for helper objects
|
// Getters for helper objects
|
||||||
|
|
||||||
makeSigner = () => new Nip01Signer(this.params.clientSecret)
|
makeSigner = () => new Nip01Signer(this.params.clientSecret)
|
||||||
@@ -307,9 +288,11 @@ export class Nip46Broker extends Emitter {
|
|||||||
makeSender = () => {
|
makeSender = () => {
|
||||||
const sender = new Nip46Sender(this.signer, this.params)
|
const sender = new Nip46Sender(this.signer, this.params)
|
||||||
|
|
||||||
sender.on(Nip46Event.Send, (data: any) => {
|
if (nip46Context.debug) {
|
||||||
this.params.debug?.("nip46 send:", data)
|
sender.on(Nip46Event.Send, (data: any) => {
|
||||||
})
|
console.log("nip46 send:", data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return sender
|
return sender
|
||||||
}
|
}
|
||||||
@@ -317,27 +300,18 @@ export class Nip46Broker extends Emitter {
|
|||||||
makeReceiver = () => {
|
makeReceiver = () => {
|
||||||
const receiver = new Nip46Receiver(this.signer, this.params)
|
const receiver = new Nip46Receiver(this.signer, this.params)
|
||||||
|
|
||||||
receiver.on(Nip46Event.Receive, (data: any) => {
|
if (nip46Context.debug) {
|
||||||
this.params.debug?.("nip46 receive:", data)
|
receiver.on(Nip46Event.Receive, (data: any) => {
|
||||||
})
|
console.log("nip46 receive:", data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return receiver
|
return receiver
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lifecycle methods
|
// Lifecycle methods
|
||||||
|
|
||||||
setParams = (params: Partial<Nip46BrokerParams>) => {
|
cleanup = () => {
|
||||||
this.params = {...this.params, ...params}
|
|
||||||
|
|
||||||
// Stop everything that's stateful
|
|
||||||
this.teardown()
|
|
||||||
|
|
||||||
// Set it back up again
|
|
||||||
this.sender = this.makeSender()
|
|
||||||
this.receiver = this.makeReceiver()
|
|
||||||
}
|
|
||||||
|
|
||||||
teardown = () => {
|
|
||||||
this.sender.stop()
|
this.sender.stop()
|
||||||
this.receiver.stop()
|
this.receiver.stop()
|
||||||
}
|
}
|
||||||
@@ -382,7 +356,7 @@ export class Nip46Broker extends Emitter {
|
|||||||
if (response.result === "auth_url") return
|
if (response.result === "auth_url") return
|
||||||
|
|
||||||
if (["ack", secret].includes(response.result!)) {
|
if (["ack", secret].includes(response.result!)) {
|
||||||
this.setParams({signerPubkey: response.event.pubkey})
|
this.params.signerPubkey = response.event.pubkey
|
||||||
|
|
||||||
if (response.result === "ack") {
|
if (response.result === "ack") {
|
||||||
console.warn(
|
console.warn(
|
||||||
|
|||||||
Reference in New Issue
Block a user