applesauce-signers 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.js +1 -0
- package/dist/helpers/nostr-connect.d.ts +92 -0
- package/dist/helpers/nostr-connect.js +93 -0
- package/dist/helpers/observable.d.ts +11 -0
- package/dist/helpers/observable.js +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/interface.d.ts +15 -0
- package/dist/signers/amber-clipboard-signer.d.ts +6 -6
- package/dist/signers/extension-signer.d.ts +9 -16
- package/dist/signers/extension-signer.js +9 -20
- package/dist/signers/index.d.ts +1 -0
- package/dist/signers/index.js +1 -0
- package/dist/signers/nostr-connect-provider.d.ts +128 -0
- package/dist/signers/nostr-connect-provider.js +406 -0
- package/dist/signers/nostr-connect-signer.d.ts +26 -89
- package/dist/signers/nostr-connect-signer.js +37 -66
- package/dist/signers/password-signer.d.ts +6 -6
- package/dist/signers/password-signer.js +8 -3
- package/dist/signers/readonly-signer.d.ts +12 -13
- package/dist/signers/readonly-signer.js +6 -9
- package/dist/signers/serial-port-signer.d.ts +4 -4
- package/dist/signers/simple-signer.d.ts +2 -1
- package/package.json +6 -3
- package/dist/nip-07.d.ts +0 -20
- /package/dist/{nip-07.js → interface.js} +0 -0
|
@@ -1,34 +1,11 @@
|
|
|
1
|
-
import { kinds, verifyEvent } from "nostr-tools";
|
|
2
|
-
import { SimpleSigner } from "applesauce-signers";
|
|
3
|
-
import { createDefer } from "applesauce-core/promise";
|
|
4
|
-
import { isHexKey, unixNow } from "applesauce-core/helpers";
|
|
5
1
|
import { logger } from "applesauce-core";
|
|
6
|
-
import {
|
|
2
|
+
import { getHiddenContent, unixNow } from "applesauce-core/helpers";
|
|
3
|
+
import { createDefer } from "applesauce-core/promise";
|
|
4
|
+
import { SimpleSigner } from "applesauce-signers";
|
|
7
5
|
import { nanoid } from "nanoid";
|
|
6
|
+
import { getPublicKey, kinds, verifyEvent } from "nostr-tools";
|
|
8
7
|
import { isNIP04 } from "../helpers/encryption.js";
|
|
9
|
-
|
|
10
|
-
return !!response.error;
|
|
11
|
-
}
|
|
12
|
-
export var Permission;
|
|
13
|
-
(function (Permission) {
|
|
14
|
-
Permission["GetPublicKey"] = "get_pubic_key";
|
|
15
|
-
Permission["SignEvent"] = "sign_event";
|
|
16
|
-
Permission["Nip04Encrypt"] = "nip04_encrypt";
|
|
17
|
-
Permission["Nip04Decrypt"] = "nip04_decrypt";
|
|
18
|
-
Permission["Nip44Encrypt"] = "nip44_encrypt";
|
|
19
|
-
Permission["Nip44Decrypt"] = "nip44_decrypt";
|
|
20
|
-
})(Permission || (Permission = {}));
|
|
21
|
-
export var NostrConnectMethod;
|
|
22
|
-
(function (NostrConnectMethod) {
|
|
23
|
-
NostrConnectMethod["Connect"] = "connect";
|
|
24
|
-
NostrConnectMethod["CreateAccount"] = "create_account";
|
|
25
|
-
NostrConnectMethod["GetPublicKey"] = "get_public_key";
|
|
26
|
-
NostrConnectMethod["SignEvent"] = "sign_event";
|
|
27
|
-
NostrConnectMethod["Nip04Encrypt"] = "nip04_encrypt";
|
|
28
|
-
NostrConnectMethod["Nip04Decrypt"] = "nip04_decrypt";
|
|
29
|
-
NostrConnectMethod["Nip44Encrypt"] = "nip44_encrypt";
|
|
30
|
-
NostrConnectMethod["Nip44Decrypt"] = "nip44_decrypt";
|
|
31
|
-
})(NostrConnectMethod || (NostrConnectMethod = {}));
|
|
8
|
+
import { NostrConnectMethod, buildSigningPermissions, createNostrConnectURI, parseBunkerURI, } from "../helpers/nostr-connect.js";
|
|
32
9
|
async function defaultHandleAuth(url) {
|
|
33
10
|
window.open(url, "auth", "width=400,height=600,resizable=no,status=no,location=no,toolbar=no,menubar=no");
|
|
34
11
|
}
|
|
@@ -37,6 +14,12 @@ export class NostrConnectSigner {
|
|
|
37
14
|
publishMethod;
|
|
38
15
|
/** The active nostr subscription */
|
|
39
16
|
subscriptionMethod;
|
|
17
|
+
/** A fallback method to use for subscriptionMethod if none is pass in when creating the signer */
|
|
18
|
+
static subscriptionMethod = undefined;
|
|
19
|
+
/** A fallback method to use for publishMethod if none is pass in when creating the signer */
|
|
20
|
+
static publishMethod = undefined;
|
|
21
|
+
/** A fallback pool to use if none is pass in when creating the signer */
|
|
22
|
+
static pool = undefined;
|
|
40
23
|
log = logger.extend("NostrConnectSigner");
|
|
41
24
|
/** The local client signer */
|
|
42
25
|
signer;
|
|
@@ -58,25 +41,27 @@ export class NostrConnectSigner {
|
|
|
58
41
|
onAuth = defaultHandleAuth;
|
|
59
42
|
verifyEvent = verifyEvent;
|
|
60
43
|
/** A secret used when initiating a connection from the client side */
|
|
61
|
-
|
|
44
|
+
secret;
|
|
62
45
|
nip04;
|
|
63
46
|
nip44;
|
|
64
|
-
/** A fallback method to use for subscriptionMethod if none is pass in when creating the signer */
|
|
65
|
-
static subscriptionMethod = undefined;
|
|
66
|
-
/** A fallback method to use for publishMethod if none is pass in when creating the signer */
|
|
67
|
-
static publishMethod = undefined;
|
|
68
47
|
constructor(opts) {
|
|
69
48
|
this.relays = opts.relays;
|
|
70
49
|
this.pubkey = opts.pubkey;
|
|
71
50
|
this.remote = opts.remote;
|
|
72
|
-
|
|
51
|
+
this.secret = opts.secret || nanoid(12);
|
|
52
|
+
// Get the subscription and publish methods
|
|
53
|
+
const subscriptionMethod = opts.subscriptionMethod ||
|
|
54
|
+
opts.pool?.subscription ||
|
|
55
|
+
NostrConnectSigner.subscriptionMethod ||
|
|
56
|
+
NostrConnectSigner.pool?.subscription;
|
|
73
57
|
if (!subscriptionMethod)
|
|
74
58
|
throw new Error("Missing subscriptionMethod, either pass a method or set NostrConnectSigner.subscriptionMethod");
|
|
75
|
-
const publishMethod = opts.publishMethod || NostrConnectSigner.publishMethod;
|
|
59
|
+
const publishMethod = opts.publishMethod || opts.pool?.publish || NostrConnectSigner.publishMethod || NostrConnectSigner.pool?.publish;
|
|
76
60
|
if (!publishMethod)
|
|
77
61
|
throw new Error("Missing publishMethod, either pass a method or set NostrConnectSigner.publishMethod");
|
|
78
|
-
this
|
|
79
|
-
this.
|
|
62
|
+
// Use arrow functions so "this" isn't bound to the signer
|
|
63
|
+
this.subscriptionMethod = (relays, filters) => subscriptionMethod(relays, filters);
|
|
64
|
+
this.publishMethod = (relays, event) => publishMethod(relays, event);
|
|
80
65
|
if (opts.onAuth)
|
|
81
66
|
this.onAuth = opts.onAuth;
|
|
82
67
|
this.signer = opts?.signer || new SimpleSigner();
|
|
@@ -134,12 +119,15 @@ export class NostrConnectSigner {
|
|
|
134
119
|
if (this.remote && event.pubkey !== this.remote)
|
|
135
120
|
return;
|
|
136
121
|
try {
|
|
137
|
-
const responseStr =
|
|
138
|
-
|
|
139
|
-
|
|
122
|
+
const responseStr = getHiddenContent(event) ??
|
|
123
|
+
(isNIP04(event.content)
|
|
124
|
+
? await this.signer.nip04.decrypt(event.pubkey, event.content)
|
|
125
|
+
: await this.signer.nip44.decrypt(event.pubkey, event.content));
|
|
126
|
+
if (!responseStr)
|
|
127
|
+
return;
|
|
140
128
|
const response = JSON.parse(responseStr);
|
|
141
129
|
// handle remote signer connection
|
|
142
|
-
if (!this.remote && (response.result === "ack" || (this.
|
|
130
|
+
if (!this.remote && (response.result === "ack" || (this.secret && response.result === this.secret))) {
|
|
143
131
|
this.log("Got ack response from", event.pubkey, response.result);
|
|
144
132
|
this.isConnected = true;
|
|
145
133
|
this.remote = event.pubkey;
|
|
@@ -316,37 +304,20 @@ export class NostrConnectSigner {
|
|
|
316
304
|
}
|
|
317
305
|
/** Returns the nostrconnect:// URI for this signer */
|
|
318
306
|
getNostrConnectURI(metadata) {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
if (metadata?.image)
|
|
326
|
-
params.set("image", metadata.image);
|
|
327
|
-
if (metadata?.permissions)
|
|
328
|
-
params.set("perms", metadata.permissions.join(","));
|
|
329
|
-
for (const relay of this.relays)
|
|
330
|
-
params.append("relay", relay);
|
|
331
|
-
const client = getPublicKey(this.signer.key);
|
|
332
|
-
return `nostrconnect://${client}?` + params.toString();
|
|
307
|
+
return createNostrConnectURI({
|
|
308
|
+
client: getPublicKey(this.signer.key),
|
|
309
|
+
secret: this.secret,
|
|
310
|
+
relays: this.relays,
|
|
311
|
+
metadata,
|
|
312
|
+
});
|
|
333
313
|
}
|
|
334
314
|
/** Parses a bunker:// URI */
|
|
335
315
|
static parseBunkerURI(uri) {
|
|
336
|
-
|
|
337
|
-
// firefox puts pubkey part in host, chrome puts pubkey in pathname
|
|
338
|
-
const remote = url.host || url.pathname.replace("//", "");
|
|
339
|
-
if (!isHexKey(remote))
|
|
340
|
-
throw new Error("Invalid connection URI");
|
|
341
|
-
const relays = url.searchParams.getAll("relay");
|
|
342
|
-
if (relays.length === 0)
|
|
343
|
-
throw new Error("Missing relays");
|
|
344
|
-
const secret = url.searchParams.get("secret") ?? undefined;
|
|
345
|
-
return { remote, relays, secret };
|
|
316
|
+
return parseBunkerURI(uri);
|
|
346
317
|
}
|
|
347
318
|
/** Builds an array of signing permissions for event kinds */
|
|
348
319
|
static buildSigningPermissions(kinds) {
|
|
349
|
-
return
|
|
320
|
+
return buildSigningPermissions(kinds);
|
|
350
321
|
}
|
|
351
322
|
/** Create a {@link NostrConnectSigner} from a bunker:// URI */
|
|
352
323
|
static async fromBunkerURI(uri, options) {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { EventTemplate } from "nostr-tools";
|
|
2
2
|
import { Deferred } from "applesauce-core/promise";
|
|
3
|
-
import {
|
|
3
|
+
import { ISigner } from "../interface.js";
|
|
4
4
|
/** A NIP-49 (Private Key Encryption) signer */
|
|
5
|
-
export declare class PasswordSigner implements
|
|
5
|
+
export declare class PasswordSigner implements ISigner {
|
|
6
6
|
key: Uint8Array | null;
|
|
7
7
|
ncryptsec?: string;
|
|
8
8
|
nip04: {
|
|
9
|
-
encrypt: (pubkey: string, plaintext: string) => Promise<string
|
|
10
|
-
decrypt: (pubkey: string, ciphertext: string) => Promise<string
|
|
9
|
+
encrypt: (pubkey: string, plaintext: string) => Promise<string>;
|
|
10
|
+
decrypt: (pubkey: string, ciphertext: string) => Promise<string>;
|
|
11
11
|
};
|
|
12
12
|
nip44: {
|
|
13
|
-
encrypt: (pubkey: string, plaintext: string) => Promise<string
|
|
14
|
-
decrypt: (pubkey: string, ciphertext: string) => Promise<string
|
|
13
|
+
encrypt: (pubkey: string, plaintext: string) => Promise<string>;
|
|
14
|
+
decrypt: (pubkey: string, ciphertext: string) => Promise<string>;
|
|
15
15
|
};
|
|
16
16
|
get unlocked(): boolean;
|
|
17
17
|
constructor();
|
|
@@ -52,9 +52,14 @@ export class PasswordSigner {
|
|
|
52
52
|
if (this.key)
|
|
53
53
|
return;
|
|
54
54
|
if (this.ncryptsec) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
try {
|
|
56
|
+
this.key = decrypt(this.ncryptsec, password);
|
|
57
|
+
if (!this.key)
|
|
58
|
+
throw new Error("Failed to decrypt key");
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
throw new Error("failed to decrypt key: " + (error instanceof Error ? error.message : String(error)));
|
|
62
|
+
}
|
|
58
63
|
}
|
|
59
64
|
else
|
|
60
65
|
throw new Error("Missing ncryptsec");
|
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
import { VerifiedEvent } from "nostr-tools";
|
|
2
|
-
import {
|
|
2
|
+
import { ISigner } from "../interface.js";
|
|
3
3
|
/** A signer that only implements getPublicKey and throws on ever other method */
|
|
4
|
-
export declare class ReadonlySigner implements
|
|
4
|
+
export declare class ReadonlySigner implements ISigner {
|
|
5
5
|
private pubkey;
|
|
6
6
|
nip04: {
|
|
7
|
-
encrypt: (pubkey: string, plaintext: string) => Promise<string
|
|
8
|
-
decrypt: (pubkey: string, ciphertext: string) => Promise<string
|
|
7
|
+
encrypt: (pubkey: string, plaintext: string) => Promise<string>;
|
|
8
|
+
decrypt: (pubkey: string, ciphertext: string) => Promise<string>;
|
|
9
9
|
};
|
|
10
10
|
nip44: {
|
|
11
|
-
encrypt: (pubkey: string, plaintext: string) => Promise<string
|
|
12
|
-
decrypt: (pubkey: string, ciphertext: string) => Promise<string
|
|
11
|
+
encrypt: (pubkey: string, plaintext: string) => Promise<string>;
|
|
12
|
+
decrypt: (pubkey: string, ciphertext: string) => Promise<string>;
|
|
13
13
|
};
|
|
14
14
|
constructor(pubkey: string);
|
|
15
|
-
getPublicKey(): string
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
nip44Decrypt(): string;
|
|
15
|
+
getPublicKey(): Promise<string>;
|
|
16
|
+
signEvent(): Promise<VerifiedEvent>;
|
|
17
|
+
nip04Encrypt(): Promise<string>;
|
|
18
|
+
nip04Decrypt(): Promise<string>;
|
|
19
|
+
nip44Encrypt(): Promise<string>;
|
|
20
|
+
nip44Decrypt(): Promise<string>;
|
|
22
21
|
/** Creates a ReadonlySigner from a hex public key or NIP-19 npub */
|
|
23
22
|
static fromPubkey(pubkey: string): ReadonlySigner;
|
|
24
23
|
}
|
|
@@ -17,25 +17,22 @@ export class ReadonlySigner {
|
|
|
17
17
|
decrypt: this.nip44Decrypt.bind(this),
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
|
-
getPublicKey() {
|
|
20
|
+
async getPublicKey() {
|
|
21
21
|
return this.pubkey;
|
|
22
22
|
}
|
|
23
|
-
|
|
24
|
-
return {};
|
|
25
|
-
}
|
|
26
|
-
signEvent() {
|
|
23
|
+
async signEvent() {
|
|
27
24
|
throw new Error("Cant sign events with readonly");
|
|
28
25
|
}
|
|
29
|
-
nip04Encrypt() {
|
|
26
|
+
async nip04Encrypt() {
|
|
30
27
|
throw new Error("Cant encrypt with readonly");
|
|
31
28
|
}
|
|
32
|
-
nip04Decrypt() {
|
|
29
|
+
async nip04Decrypt() {
|
|
33
30
|
throw new Error("Cant decrypt with readonly");
|
|
34
31
|
}
|
|
35
|
-
nip44Encrypt() {
|
|
32
|
+
async nip44Encrypt() {
|
|
36
33
|
throw new Error("Cant encrypt with readonly");
|
|
37
34
|
}
|
|
38
|
-
nip44Decrypt() {
|
|
35
|
+
async nip44Decrypt() {
|
|
39
36
|
throw new Error("Cant decrypt with readonly");
|
|
40
37
|
}
|
|
41
38
|
/** Creates a ReadonlySigner from a hex public key or NIP-19 npub */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Deferred } from "applesauce-core/promise";
|
|
2
2
|
import { EventTemplate, verifyEvent } from "nostr-tools";
|
|
3
|
-
import {
|
|
3
|
+
import { ISigner } from "../interface.js";
|
|
4
4
|
type Callback = () => void;
|
|
5
5
|
type DeviceOpts = {
|
|
6
6
|
onConnect?: Callback;
|
|
@@ -9,15 +9,15 @@ type DeviceOpts = {
|
|
|
9
9
|
onDone?: Callback;
|
|
10
10
|
};
|
|
11
11
|
/** A signer that works with [nostr-signing-device](https://github.com/lnbits/nostr-signing-device) */
|
|
12
|
-
export declare class SerialPortSigner implements
|
|
12
|
+
export declare class SerialPortSigner implements ISigner {
|
|
13
13
|
protected log: import("debug").Debugger;
|
|
14
14
|
protected writer: WritableStreamDefaultWriter<string> | null;
|
|
15
15
|
pubkey?: string;
|
|
16
16
|
get isConnected(): boolean;
|
|
17
17
|
verifyEvent: typeof verifyEvent;
|
|
18
18
|
nip04: {
|
|
19
|
-
encrypt: (pubkey: string, plaintext: string) => Promise<string
|
|
20
|
-
decrypt: (pubkey: string, ciphertext: string) => Promise<string
|
|
19
|
+
encrypt: (pubkey: string, plaintext: string) => Promise<string>;
|
|
20
|
+
decrypt: (pubkey: string, ciphertext: string) => Promise<string>;
|
|
21
21
|
};
|
|
22
22
|
constructor();
|
|
23
23
|
protected lastCommand: Deferred<string> | null;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EventTemplate } from "nostr-tools";
|
|
2
|
+
import { ISigner } from "../interface.js";
|
|
2
3
|
/** A Simple NIP-07 signer class */
|
|
3
|
-
export declare class SimpleSigner {
|
|
4
|
+
export declare class SimpleSigner implements ISigner {
|
|
4
5
|
key: Uint8Array;
|
|
5
6
|
constructor(key?: Uint8Array);
|
|
6
7
|
getPublicKey(): Promise<string>;
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "applesauce-signers",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Signer classes for applesauce",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"keywords": [
|
|
9
9
|
"nostr",
|
|
10
|
+
"signer",
|
|
11
|
+
"nostr-connect",
|
|
10
12
|
"applesauce"
|
|
11
13
|
],
|
|
12
14
|
"author": "hzrd149",
|
|
@@ -36,7 +38,7 @@
|
|
|
36
38
|
"@noble/hashes": "^1.7.1",
|
|
37
39
|
"@noble/secp256k1": "^1.7.1",
|
|
38
40
|
"@scure/base": "^1.2.4",
|
|
39
|
-
"applesauce-core": "^
|
|
41
|
+
"applesauce-core": "^3.0.0",
|
|
40
42
|
"debug": "^4.4.0",
|
|
41
43
|
"nanoid": "^5.0.9",
|
|
42
44
|
"nostr-tools": "^2.13"
|
|
@@ -45,7 +47,8 @@
|
|
|
45
47
|
"@types/debug": "^4.1.12",
|
|
46
48
|
"@types/dom-serial": "^1.0.6",
|
|
47
49
|
"typescript": "^5.8.3",
|
|
48
|
-
"vitest": "^3.1.3"
|
|
50
|
+
"vitest": "^3.1.3",
|
|
51
|
+
"vitest-websocket-mock": "^0.5.0"
|
|
49
52
|
},
|
|
50
53
|
"funding": {
|
|
51
54
|
"type": "lightning",
|
package/dist/nip-07.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { EventTemplate, NostrEvent } from "nostr-tools";
|
|
2
|
-
export type Nip07Interface = {
|
|
3
|
-
getPublicKey: () => Promise<string> | string;
|
|
4
|
-
signEvent: (template: EventTemplate) => Promise<NostrEvent> | NostrEvent;
|
|
5
|
-
getRelays?: () => Record<string, {
|
|
6
|
-
read: boolean;
|
|
7
|
-
write: boolean;
|
|
8
|
-
}> | Promise<Record<string, {
|
|
9
|
-
read: boolean;
|
|
10
|
-
write: boolean;
|
|
11
|
-
}>>;
|
|
12
|
-
nip04?: {
|
|
13
|
-
encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
|
|
14
|
-
decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
|
|
15
|
-
};
|
|
16
|
-
nip44?: {
|
|
17
|
-
encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
|
|
18
|
-
decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
|
|
19
|
-
};
|
|
20
|
-
};
|
|
File without changes
|