Throttle nip46 signer requests
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import {Emitter, tryCatch, randomId, equals, now} from "@welshman/lib"
|
import {Emitter, sleep, tryCatch, randomId, equals, now} from "@welshman/lib"
|
||||||
import {createEvent, TrustedEvent, StampedEvent, NOSTR_CONNECT} from "@welshman/util"
|
import {createEvent, TrustedEvent, StampedEvent, NOSTR_CONNECT} from "@welshman/util"
|
||||||
import {subscribe, publish, Subscription} from "@welshman/net"
|
import {subscribe, publish, Subscription} from "@welshman/net"
|
||||||
import {ISigner, decrypt, hash, own} from '../util'
|
import {ISigner, decrypt, hash, own} from '../util'
|
||||||
@@ -24,6 +24,12 @@ export type Nip46Response = {
|
|||||||
result?: string
|
result?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Request = {
|
||||||
|
method: string
|
||||||
|
params: string[]
|
||||||
|
resolve: (result: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
let singleton: Nip46Broker
|
let singleton: Nip46Broker
|
||||||
|
|
||||||
export class Nip46Broker extends Emitter {
|
export class Nip46Broker extends Emitter {
|
||||||
@@ -31,7 +37,9 @@ export class Nip46Broker extends Emitter {
|
|||||||
#handler: Nip46Handler
|
#handler: Nip46Handler
|
||||||
#algorithm: Nip46Algorithm
|
#algorithm: Nip46Algorithm
|
||||||
#closed = false
|
#closed = false
|
||||||
|
#processing = false
|
||||||
#connectResult?: string
|
#connectResult?: string
|
||||||
|
#queue: Request[] = []
|
||||||
#sub?: Subscription
|
#sub?: Subscription
|
||||||
|
|
||||||
static get(params: Nip46BrokerParams) {
|
static get(params: Nip46BrokerParams) {
|
||||||
@@ -91,6 +99,31 @@ export class Nip46Broker extends Emitter {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#processQueue = async () => {
|
||||||
|
if (this.#processing) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#processing = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (this.#queue.length > 0) {
|
||||||
|
const [{method, params, resolve}] = this.#queue.splice(0, 1)
|
||||||
|
|
||||||
|
// Throttle requests to the signer so the user isn't overwhelmed by dialogs, but time
|
||||||
|
// out and move on to other requests if they're ignored
|
||||||
|
// Note: currenlty throttle is too low to help with dialogs, but blocking prevents
|
||||||
|
// important user actions
|
||||||
|
await Promise.race([
|
||||||
|
this.request(method, params).then(resolve),
|
||||||
|
sleep(100),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
this.#processing = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
request = async (method: string, params: string[]) => {
|
request = async (method: string, params: string[]) => {
|
||||||
if (this.#closed) {
|
if (this.#closed) {
|
||||||
throw new Error("Attempted to make a nip46 request with a closed broker")
|
throw new Error("Attempted to make a nip46 request with a closed broker")
|
||||||
@@ -126,44 +159,50 @@ export class Nip46Broker extends Emitter {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enqueue = (method: string, params: string[]) =>
|
||||||
|
new Promise<string>(resolve => {
|
||||||
|
this.#queue.push({method, params, resolve})
|
||||||
|
this.#processQueue()
|
||||||
|
})
|
||||||
|
|
||||||
createAccount = (username: string, perms = "") => {
|
createAccount = (username: string, perms = "") => {
|
||||||
if (!this.#handler.domain) {
|
if (!this.#handler.domain) {
|
||||||
throw new Error("Unable to create an account without a handler domain")
|
throw new Error("Unable to create an account without a handler domain")
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.request("create_account", [username, this.#handler.domain, "", perms])
|
return this.enqueue("create_account", [username, this.#handler.domain, "", perms])
|
||||||
}
|
}
|
||||||
|
|
||||||
connect = async (token = "", perms = "") => {
|
connect = async (token = "", perms = "") => {
|
||||||
if (!this.#connectResult) {
|
if (!this.#connectResult) {
|
||||||
const params = ["", token, perms]
|
const params = ["", token, perms]
|
||||||
|
|
||||||
this.#connectResult = await this.request("connect", params)
|
this.#connectResult = await this.enqueue("connect", params)
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.#connectResult === "ack"
|
return this.#connectResult === "ack"
|
||||||
}
|
}
|
||||||
|
|
||||||
getPublicKey = () => this.request("get_public_key", [])
|
getPublicKey = () => this.enqueue("get_public_key", [])
|
||||||
|
|
||||||
signEvent = async (event: StampedEvent) => {
|
signEvent = async (event: StampedEvent) => {
|
||||||
return JSON.parse(await this.request("sign_event", [JSON.stringify(event)]) as string)
|
return JSON.parse(await this.enqueue("sign_event", [JSON.stringify(event)]) as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
nip04Encrypt = (pk: string, message: string) => {
|
nip04Encrypt = (pk: string, message: string) => {
|
||||||
return this.request("nip04_encrypt", [pk, message])
|
return this.enqueue("nip04_encrypt", [pk, message])
|
||||||
}
|
}
|
||||||
|
|
||||||
nip04Decrypt = (pk: string, message: string) => {
|
nip04Decrypt = (pk: string, message: string) => {
|
||||||
return this.request("nip04_decrypt", [pk, message])
|
return this.enqueue("nip04_decrypt", [pk, message])
|
||||||
}
|
}
|
||||||
|
|
||||||
nip44Encrypt = (pk: string, message: string) => {
|
nip44Encrypt = (pk: string, message: string) => {
|
||||||
return this.request("nip44_encrypt", [pk, message])
|
return this.enqueue("nip44_encrypt", [pk, message])
|
||||||
}
|
}
|
||||||
|
|
||||||
nip44Decrypt = (pk: string, message: string) => {
|
nip44Decrypt = (pk: string, message: string) => {
|
||||||
return this.request("nip44_decrypt", [pk, message])
|
return this.enqueue("nip44_decrypt", [pk, message])
|
||||||
}
|
}
|
||||||
|
|
||||||
teardown = () => {
|
teardown = () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user