Add sign timeout to thunk
This commit is contained in:
@@ -20,8 +20,11 @@ import { makeEvent } from '@welshman/util'
|
|||||||
import { ISigner, Nip01Signer, makeSecret } from '@welshman/signer'
|
import { ISigner, Nip01Signer, makeSecret } from '@welshman/signer'
|
||||||
|
|
||||||
const signer: ISigner = new Nip01Signer(makeSecret())
|
const signer: ISigner = new Nip01Signer(makeSecret())
|
||||||
|
const options = {
|
||||||
|
signal: AbortSignal.timeout(10_000),
|
||||||
|
}
|
||||||
|
|
||||||
signer.sign(makeEvent(1)).then(signedEvent => console.log(signedEvent))
|
signer.sign(makeEvent(1), options).then(signedEvent => console.log(signedEvent))
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|||||||
@@ -5,9 +5,15 @@ It includes methods for signing messages, verifying signatures, and encrypting/d
|
|||||||
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
|
export type SignOptions = {
|
||||||
|
signal?: AbortSignal
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SignWithOptions = (event: StampedEvent, options?: SignOptions) => Promise<SignedEvent>
|
||||||
|
|
||||||
interface ISigner {
|
interface ISigner {
|
||||||
// Core signing functionality
|
// Core signing functionality
|
||||||
sign: (event: StampedEvent) => Promise<SignedEvent>
|
sign: SignWithOptions
|
||||||
getPubkey: () => Promise<string>
|
getPubkey: () => Promise<string>
|
||||||
|
|
||||||
// Encryption capabilities
|
// Encryption capabilities
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class Nip01Signer implements ISigner {
|
|||||||
constructor(private secret: string)
|
constructor(private secret: string)
|
||||||
|
|
||||||
// ISigner implementation
|
// ISigner implementation
|
||||||
sign: (event: StampedEvent) => Promise<SignedEvent>
|
sign: SignWithOptions
|
||||||
getPubkey: () => Promise<string>
|
getPubkey: () => Promise<string>
|
||||||
nip04: { encrypt, decrypt }
|
nip04: { encrypt, decrypt }
|
||||||
nip44: { encrypt, decrypt }
|
nip44: { encrypt, decrypt }
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class Nip55Signer implements ISigner {
|
|||||||
constructor(private secret: string)
|
constructor(private secret: string)
|
||||||
|
|
||||||
// ISigner implementation
|
// ISigner implementation
|
||||||
sign: (event: StampedEvent) => Promise<SignedEvent>
|
sign: SignWithOptions
|
||||||
getPubkey: () => Promise<string>
|
getPubkey: () => Promise<string>
|
||||||
nip04: { encrypt, decrypt }
|
nip04: { encrypt, decrypt }
|
||||||
nip44: { encrypt, decrypt }
|
nip44: { encrypt, decrypt }
|
||||||
|
|||||||
@@ -132,9 +132,11 @@ export class Thunk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
event = await signer.sign(event)
|
event = await signer.sign(event, {
|
||||||
|
signal: AbortSignal.timeout(15_000),
|
||||||
|
})
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
return this._fail(`Failed to sign event: ${String(e.error || e)}`)
|
return this._fail(String(e || "Failed to sign event"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,16 @@
|
|||||||
import {StampedEvent} from "@welshman/util"
|
import {StampedEvent} from "@welshman/util"
|
||||||
import {nip04, nip44, own, hash, sign, getPubkey, ISigner, makeSecret} from "../util.js"
|
import {
|
||||||
|
nip04,
|
||||||
|
nip44,
|
||||||
|
own,
|
||||||
|
hash,
|
||||||
|
sign,
|
||||||
|
getPubkey,
|
||||||
|
ISigner,
|
||||||
|
SignOptions,
|
||||||
|
signWithOptions,
|
||||||
|
makeSecret,
|
||||||
|
} from "../util.js"
|
||||||
|
|
||||||
export class Nip01Signer implements ISigner {
|
export class Nip01Signer implements ISigner {
|
||||||
#pubkey: string
|
#pubkey: string
|
||||||
@@ -14,7 +25,8 @@ export class Nip01Signer implements ISigner {
|
|||||||
|
|
||||||
getPubkey = async () => this.#pubkey
|
getPubkey = async () => this.#pubkey
|
||||||
|
|
||||||
sign = async (event: StampedEvent) => sign(hash(own(event, this.#pubkey)), this.secret)
|
sign = (event: StampedEvent, options: SignOptions = {}) =>
|
||||||
|
signWithOptions(sign(hash(own(event, this.#pubkey)), this.secret), options)
|
||||||
|
|
||||||
nip04 = {
|
nip04 = {
|
||||||
encrypt: async (pubkey: string, message: string) => nip04.encrypt(pubkey, this.secret, message),
|
encrypt: async (pubkey: string, message: string) => nip04.encrypt(pubkey, this.secret, message),
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
import {StampedEvent} from "@welshman/util"
|
import {StampedEvent} from "@welshman/util"
|
||||||
import {hash, own, Sign, ISigner, EncryptionImplementation} from "../util.js"
|
import {
|
||||||
|
hash,
|
||||||
|
own,
|
||||||
|
signWithOptions,
|
||||||
|
SignOptions,
|
||||||
|
Sign,
|
||||||
|
ISigner,
|
||||||
|
EncryptionImplementation,
|
||||||
|
} from "../util.js"
|
||||||
|
|
||||||
export type Nip07 = {
|
export type Nip07 = {
|
||||||
signEvent: Sign
|
signEvent: Sign
|
||||||
@@ -33,11 +41,11 @@ export class Nip07Signer implements ISigner {
|
|||||||
|
|
||||||
getPubkey = async () => this.#then<string>(ext => ext.getPublicKey() as string)
|
getPubkey = async () => this.#then<string>(ext => ext.getPublicKey() as string)
|
||||||
|
|
||||||
sign = async (template: StampedEvent) => {
|
sign = (template: StampedEvent, options: SignOptions = {}) =>
|
||||||
const event = hash(own(template, await this.getPubkey()))
|
signWithOptions(
|
||||||
|
this.#then(async ext => ext.signEvent(hash(own(template, await ext.getPublicKey()!)))),
|
||||||
return this.#then(ext => ext.signEvent(event))
|
options,
|
||||||
}
|
)
|
||||||
|
|
||||||
nip04 = {
|
nip04 = {
|
||||||
encrypt: (pubkey: string, message: string) =>
|
encrypt: (pubkey: string, message: string) =>
|
||||||
|
|||||||
@@ -7,7 +7,15 @@ import {
|
|||||||
NOSTR_CONNECT,
|
NOSTR_CONNECT,
|
||||||
} from "@welshman/util"
|
} from "@welshman/util"
|
||||||
import {publish, request, AdapterContext} from "@welshman/net"
|
import {publish, request, AdapterContext} from "@welshman/net"
|
||||||
import {ISigner, EncryptionImplementation, decrypt, hash, own} from "../util.js"
|
import {
|
||||||
|
ISigner,
|
||||||
|
EncryptionImplementation,
|
||||||
|
signWithOptions,
|
||||||
|
SignOptions,
|
||||||
|
decrypt,
|
||||||
|
hash,
|
||||||
|
own,
|
||||||
|
} from "../util.js"
|
||||||
import {Nip01Signer} from "./nip01.js"
|
import {Nip01Signer} from "./nip01.js"
|
||||||
|
|
||||||
export type Nip46Context = {
|
export type Nip46Context = {
|
||||||
@@ -463,6 +471,9 @@ export class Nip46Signer implements ISigner {
|
|||||||
return this.pubkey
|
return this.pubkey
|
||||||
}
|
}
|
||||||
|
|
||||||
sign = async (template: StampedEvent) =>
|
sign = (template: StampedEvent, options: SignOptions = {}) =>
|
||||||
this.broker.signEvent(hash(own(template, await this.getPubkey())))
|
signWithOptions(
|
||||||
|
this.getPubkey().then(pubkey => this.broker.signEvent(hash(own(template, pubkey)))),
|
||||||
|
options,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {NostrSignerPlugin, AppInfo} from "nostr-signer-capacitor-plugin"
|
import {NostrSignerPlugin, AppInfo} from "nostr-signer-capacitor-plugin"
|
||||||
import {decode} from "nostr-tools/nip19"
|
import {decode} from "nostr-tools/nip19"
|
||||||
import {SignedEvent, StampedEvent} from "@welshman/util"
|
import {SignedEvent, StampedEvent} from "@welshman/util"
|
||||||
import {hash, own, ISigner} from "../util.js"
|
import {hash, own, signWithOptions, SignOptions, ISigner} from "../util.js"
|
||||||
|
|
||||||
export const getNip55 = async (): Promise<AppInfo[]> => {
|
export const getNip55 = async (): Promise<AppInfo[]> => {
|
||||||
const {apps} = await NostrSignerPlugin.getInstalledSignerApps()
|
const {apps} = await NostrSignerPlugin.getInstalledSignerApps()
|
||||||
@@ -64,21 +64,23 @@ export class Nip55Signer implements ISigner {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
sign = async (template: StampedEvent): Promise<SignedEvent> => {
|
sign = (template: StampedEvent, options: SignOptions = {}): Promise<SignedEvent> =>
|
||||||
const pubkey = await this.getPubkey() // hex-encoded public key
|
signWithOptions(
|
||||||
const npub = this.#npub! // Bech32-encoded public key
|
this.getPubkey().then(pubkey => {
|
||||||
const event = {sig: "", ...hash(own(template, pubkey))}
|
const hashedEvent = hash(own(template, pubkey))
|
||||||
|
|
||||||
return this.#then(async signer => {
|
return this.#then(async signer => {
|
||||||
const {event: signedEventJson} = await signer.signEvent({
|
const {event: json} = await signer.signEvent({
|
||||||
eventJson: JSON.stringify(event),
|
eventJson: JSON.stringify({sig: "", ...hashedEvent}),
|
||||||
eventId: event.id,
|
eventId: hashedEvent.id,
|
||||||
npub: npub,
|
npub: this.#npub!,
|
||||||
})
|
})
|
||||||
const signedEvent = JSON.parse(signedEventJson) as SignedEvent
|
|
||||||
return signedEvent
|
return JSON.parse(json) as SignedEvent
|
||||||
})
|
})
|
||||||
}
|
}),
|
||||||
|
options,
|
||||||
|
)
|
||||||
|
|
||||||
nip04 = {
|
nip04 = {
|
||||||
encrypt: async (recipientPubKey: string, message: string): Promise<string> => {
|
encrypt: async (recipientPubKey: string, message: string): Promise<string> => {
|
||||||
|
|||||||
@@ -44,6 +44,12 @@ export const nip44 = {
|
|||||||
|
|
||||||
export type Sign = (event: StampedEvent) => Promise<SignedEvent>
|
export type Sign = (event: StampedEvent) => Promise<SignedEvent>
|
||||||
|
|
||||||
|
export type SignOptions = {
|
||||||
|
signal?: AbortSignal
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SignWithOptions = (event: StampedEvent, options?: SignOptions) => Promise<SignedEvent>
|
||||||
|
|
||||||
export type Encrypt = (pubkey: string, message: string) => Promise<string>
|
export type Encrypt = (pubkey: string, message: string) => Promise<string>
|
||||||
|
|
||||||
export type Decrypt = (pubkey: string, message: string) => Promise<string>
|
export type Decrypt = (pubkey: string, message: string) => Promise<string>
|
||||||
@@ -54,7 +60,7 @@ export type EncryptionImplementation = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ISigner {
|
export interface ISigner {
|
||||||
sign: Sign
|
sign: SignWithOptions
|
||||||
nip04: EncryptionImplementation
|
nip04: EncryptionImplementation
|
||||||
nip44: EncryptionImplementation
|
nip44: EncryptionImplementation
|
||||||
getPubkey: () => Promise<string>
|
getPubkey: () => Promise<string>
|
||||||
@@ -75,8 +81,8 @@ export class WrappedSigner extends Emitter implements ISigner {
|
|||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
sign(event: StampedEvent) {
|
sign(event: StampedEvent, options: SignOptions = {}) {
|
||||||
return this.wrapMethod("sign", () => this.signer.sign(event))
|
return this.wrapMethod("sign", () => this.signer.sign(event, options))
|
||||||
}
|
}
|
||||||
|
|
||||||
getPubkey() {
|
getPubkey() {
|
||||||
@@ -97,3 +103,12 @@ export class WrappedSigner extends Emitter implements ISigner {
|
|||||||
this.wrapMethod("nip44.decrypt", () => this.signer.nip44.decrypt(pubkey, message)),
|
this.wrapMethod("nip44.decrypt", () => this.signer.nip44.decrypt(pubkey, message)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const signWithOptions = (
|
||||||
|
promise: Promise<SignedEvent> | SignedEvent,
|
||||||
|
options: SignOptions,
|
||||||
|
) =>
|
||||||
|
new Promise<SignedEvent>((resolve, reject) => {
|
||||||
|
Promise.resolve(promise).then(resolve)
|
||||||
|
options.signal?.addEventListener("abort", () => reject("Signing was aborted"))
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user