applesauce-signers 0.0.0-next-20250315131629 → 0.0.0-next-20250323173930
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.
|
@@ -13,6 +13,7 @@ export declare class ExtensionSigner implements Nip07Interface {
|
|
|
13
13
|
encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
|
|
14
14
|
decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
|
|
15
15
|
} | undefined;
|
|
16
|
+
protected pubkey: string | undefined;
|
|
16
17
|
getPublicKey(): string | Promise<string>;
|
|
17
18
|
getRelays(): Record<string, {
|
|
18
19
|
read: boolean;
|
|
@@ -9,10 +9,22 @@ export class ExtensionSigner {
|
|
|
9
9
|
get nip44() {
|
|
10
10
|
return window.nostr?.nip44;
|
|
11
11
|
}
|
|
12
|
+
pubkey = undefined;
|
|
12
13
|
getPublicKey() {
|
|
13
14
|
if (!window.nostr)
|
|
14
15
|
throw new ExtensionMissingError("Signer extension missing");
|
|
15
|
-
|
|
16
|
+
if (this.pubkey)
|
|
17
|
+
return this.pubkey;
|
|
18
|
+
const p = window.nostr.getPublicKey();
|
|
19
|
+
if (p instanceof Promise)
|
|
20
|
+
return p.then((pubkey) => {
|
|
21
|
+
this.pubkey = pubkey;
|
|
22
|
+
return pubkey;
|
|
23
|
+
});
|
|
24
|
+
else {
|
|
25
|
+
this.pubkey = p;
|
|
26
|
+
return p;
|
|
27
|
+
}
|
|
16
28
|
}
|
|
17
29
|
getRelays() {
|
|
18
30
|
if (!window.nostr)
|
|
@@ -64,17 +64,22 @@ export type NostrConnectSignerOptions = {
|
|
|
64
64
|
remote?: string;
|
|
65
65
|
/** Users pubkey */
|
|
66
66
|
pubkey?: string;
|
|
67
|
-
};
|
|
68
|
-
export type NostrConnectConnectionMethods = {
|
|
69
|
-
/** A method that is called when the subscription needs to be updated */
|
|
70
|
-
onSubOpen: (filters: Filter[], relays: string[], onEvent: (event: NostrEvent) => void) => Promise<void>;
|
|
71
|
-
/** A method called when the subscription should be closed */
|
|
72
|
-
onSubClose: () => Promise<void>;
|
|
73
|
-
/** A method that is called when an event needs to be published */
|
|
74
|
-
onPublishEvent: (event: NostrEvent, relays: string[]) => Promise<void>;
|
|
75
67
|
/** A method for handling "auth" requests */
|
|
76
68
|
onAuth?: (url: string) => Promise<void>;
|
|
77
69
|
};
|
|
70
|
+
interface Unsubscribable {
|
|
71
|
+
unsubscribe(): void;
|
|
72
|
+
}
|
|
73
|
+
interface Observer<T> {
|
|
74
|
+
next: (value: T) => void;
|
|
75
|
+
error: (err: any) => void;
|
|
76
|
+
complete: () => void;
|
|
77
|
+
}
|
|
78
|
+
type Subscribable<T extends unknown> = {
|
|
79
|
+
subscribe: (observer: Partial<Observer<T>>) => Unsubscribable;
|
|
80
|
+
};
|
|
81
|
+
export type NostrSubscriptionMethod = (filters: Filter[], relays: string[]) => Subscribable<NostrEvent>;
|
|
82
|
+
export type NostrPublishMethod = (event: NostrEvent, relays: string[]) => void | Promise<void>;
|
|
78
83
|
export type NostrConnectAppMetadata = {
|
|
79
84
|
name?: string;
|
|
80
85
|
image?: string;
|
|
@@ -82,12 +87,10 @@ export type NostrConnectAppMetadata = {
|
|
|
82
87
|
permissions?: string[];
|
|
83
88
|
};
|
|
84
89
|
export declare class NostrConnectSigner implements Nip07Interface {
|
|
85
|
-
/** A method that is called when the subscription needs to be updated */
|
|
86
|
-
onSubOpen?: (filters: Filter[], relays: string[], onEvent: (event: NostrEvent) => void) => Promise<void>;
|
|
87
|
-
/** A method called when the subscription should be closed */
|
|
88
|
-
onSubClose?: () => Promise<void>;
|
|
89
90
|
/** A method that is called when an event needs to be published */
|
|
90
|
-
|
|
91
|
+
protected publish: NostrPublishMethod;
|
|
92
|
+
/** The active nostr subscription */
|
|
93
|
+
protected subscription: NostrSubscriptionMethod;
|
|
91
94
|
protected log: import("debug").Debugger;
|
|
92
95
|
/** The local client signer */
|
|
93
96
|
signer: SimpleSigner;
|
|
@@ -102,6 +105,7 @@ export declare class NostrConnectSigner implements Nip07Interface {
|
|
|
102
105
|
remote?: string;
|
|
103
106
|
/** Client pubkey */
|
|
104
107
|
get clientPubkey(): string;
|
|
108
|
+
/** A method for handling "auth" requests */
|
|
105
109
|
onAuth: (url: string) => Promise<void>;
|
|
106
110
|
verifyEvent: typeof verifyEvent;
|
|
107
111
|
/** A secret used when initiating a connection from the client side */
|
|
@@ -114,7 +118,9 @@ export declare class NostrConnectSigner implements Nip07Interface {
|
|
|
114
118
|
encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
|
|
115
119
|
decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
|
|
116
120
|
} | undefined;
|
|
117
|
-
constructor(
|
|
121
|
+
constructor(subscription: NostrSubscriptionMethod, publish: NostrPublishMethod, opts: NostrConnectSignerOptions);
|
|
122
|
+
/** The currently active REQ subscription */
|
|
123
|
+
protected req?: Unsubscribable;
|
|
118
124
|
/** Open the connection */
|
|
119
125
|
open(): Promise<void>;
|
|
120
126
|
/** Close the connection */
|
|
@@ -155,7 +161,7 @@ export declare class NostrConnectSigner implements Nip07Interface {
|
|
|
155
161
|
/** Builds an array of signing permissions for event kinds */
|
|
156
162
|
static buildSigningPermissions(kinds: number[]): string[];
|
|
157
163
|
/** Create a {@link NostrConnectSigner} from a bunker:// URI */
|
|
158
|
-
static fromBunkerURI(uri: string, options:
|
|
164
|
+
static fromBunkerURI(uri: string, subscription: NostrSubscriptionMethod, publish: NostrPublishMethod, options: Omit<NostrConnectSignerOptions, "relays"> & {
|
|
159
165
|
permissions?: string[];
|
|
160
166
|
signer?: SimpleSigner;
|
|
161
167
|
}): Promise<NostrConnectSigner>;
|
|
@@ -33,14 +33,10 @@ async function defaultHandleAuth(url) {
|
|
|
33
33
|
window.open(url, "auth", "width=400,height=600,resizable=no,status=no,location=no,toolbar=no,menubar=no");
|
|
34
34
|
}
|
|
35
35
|
export class NostrConnectSigner {
|
|
36
|
-
/** A method that is called when the subscription needs to be updated */
|
|
37
|
-
onSubOpen;
|
|
38
|
-
/** A method called when the subscription should be closed */
|
|
39
|
-
onSubClose;
|
|
40
36
|
/** A method that is called when an event needs to be published */
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
publish;
|
|
38
|
+
/** The active nostr subscription */
|
|
39
|
+
subscription;
|
|
44
40
|
log = logger.extend("NostrConnectSigner");
|
|
45
41
|
/** The local client signer */
|
|
46
42
|
signer;
|
|
@@ -57,19 +53,19 @@ export class NostrConnectSigner {
|
|
|
57
53
|
get clientPubkey() {
|
|
58
54
|
return getPublicKey(this.signer.key);
|
|
59
55
|
}
|
|
56
|
+
/** A method for handling "auth" requests */
|
|
60
57
|
onAuth = defaultHandleAuth;
|
|
61
58
|
verifyEvent = verifyEvent;
|
|
62
59
|
/** A secret used when initiating a connection from the client side */
|
|
63
60
|
clientSecret = nanoid(12);
|
|
64
61
|
nip04;
|
|
65
62
|
nip44;
|
|
66
|
-
constructor(opts) {
|
|
63
|
+
constructor(subscription, publish, opts) {
|
|
67
64
|
this.relays = opts.relays;
|
|
68
65
|
this.pubkey = opts.pubkey;
|
|
69
66
|
this.remote = opts.remote;
|
|
70
|
-
this.
|
|
71
|
-
this.
|
|
72
|
-
this.onPublishEvent = opts.onPublishEvent;
|
|
67
|
+
this.subscription = subscription;
|
|
68
|
+
this.publish = publish;
|
|
73
69
|
if (opts.onAuth)
|
|
74
70
|
this.onAuth = opts.onAuth;
|
|
75
71
|
this.signer = opts?.signer || new SimpleSigner();
|
|
@@ -82,6 +78,8 @@ export class NostrConnectSigner {
|
|
|
82
78
|
decrypt: this.nip44Decrypt.bind(this),
|
|
83
79
|
};
|
|
84
80
|
}
|
|
81
|
+
/** The currently active REQ subscription */
|
|
82
|
+
req;
|
|
85
83
|
/** Open the connection */
|
|
86
84
|
async open() {
|
|
87
85
|
if (this.subscriptionOpen)
|
|
@@ -89,19 +87,21 @@ export class NostrConnectSigner {
|
|
|
89
87
|
this.subscriptionOpen = true;
|
|
90
88
|
const pubkey = await this.signer.getPublicKey();
|
|
91
89
|
// Setup subscription
|
|
92
|
-
|
|
90
|
+
this.req = this.subscription([
|
|
93
91
|
{
|
|
94
92
|
kinds: [kinds.NostrConnect],
|
|
95
93
|
"#p": [pubkey],
|
|
96
94
|
},
|
|
97
|
-
], this.relays
|
|
95
|
+
], this.relays).subscribe({
|
|
96
|
+
next: (event) => this.handleEvent(event),
|
|
97
|
+
});
|
|
98
98
|
this.log("Opened", this.relays);
|
|
99
99
|
}
|
|
100
100
|
/** Close the connection */
|
|
101
101
|
async close() {
|
|
102
102
|
this.subscriptionOpen = false;
|
|
103
103
|
this.isConnected = false;
|
|
104
|
-
|
|
104
|
+
this.req?.unsubscribe();
|
|
105
105
|
this.log("Closed");
|
|
106
106
|
}
|
|
107
107
|
requests = new Map();
|
|
@@ -178,7 +178,7 @@ export class NostrConnectSigner {
|
|
|
178
178
|
this.log(`Sending request ${id} (${method}) ${JSON.stringify(params)}`);
|
|
179
179
|
const p = createDefer();
|
|
180
180
|
this.requests.set(id, p);
|
|
181
|
-
await this.
|
|
181
|
+
await this.publish?.(event, this.relays);
|
|
182
182
|
return p;
|
|
183
183
|
}
|
|
184
184
|
/** Connect to remote signer */
|
|
@@ -318,9 +318,9 @@ export class NostrConnectSigner {
|
|
|
318
318
|
return [Permission.GetPublicKey, ...kinds.map((k) => `${Permission.SignEvent}:${k}`)];
|
|
319
319
|
}
|
|
320
320
|
/** Create a {@link NostrConnectSigner} from a bunker:// URI */
|
|
321
|
-
static async fromBunkerURI(uri, options) {
|
|
321
|
+
static async fromBunkerURI(uri, subscription, publish, options) {
|
|
322
322
|
const { remote, relays, secret } = NostrConnectSigner.parseBunkerURI(uri);
|
|
323
|
-
const client = new NostrConnectSigner({ relays, remote, ...options });
|
|
323
|
+
const client = new NostrConnectSigner(subscription, publish, { relays, remote, ...options });
|
|
324
324
|
await client.connect(secret, options.permissions);
|
|
325
325
|
return client;
|
|
326
326
|
}
|
|
@@ -3,23 +3,19 @@ import { NostrConnectSigner } from "./nostr-connect-signer.js";
|
|
|
3
3
|
import { SimpleSigner } from "./simple-signer.js";
|
|
4
4
|
describe("NostrConnectSigner", () => {
|
|
5
5
|
describe("connection", () => {
|
|
6
|
-
it("should call
|
|
6
|
+
it("should call subscription method with filters", async () => {
|
|
7
7
|
const relays = ["wss://relay.signer.com"];
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const onPublishEvent = vi.fn(async () => { });
|
|
8
|
+
const subscription = vi.fn().mockReturnValue({ subscribe: vi.fn() });
|
|
9
|
+
const publish = vi.fn(async () => { });
|
|
11
10
|
const client = new SimpleSigner();
|
|
12
11
|
const remote = new SimpleSigner();
|
|
13
|
-
const signer = new NostrConnectSigner({
|
|
14
|
-
onSubOpen,
|
|
15
|
-
onSubClose,
|
|
16
|
-
onPublishEvent,
|
|
12
|
+
const signer = new NostrConnectSigner(subscription, publish, {
|
|
17
13
|
relays,
|
|
18
14
|
remote: await remote.getPublicKey(),
|
|
19
15
|
signer: client,
|
|
20
16
|
});
|
|
21
17
|
signer.connect();
|
|
22
|
-
expect(
|
|
18
|
+
expect(subscription).toHaveBeenCalledWith([{ "#p": [await client.getPublicKey()], kinds: [24133] }], relays);
|
|
23
19
|
});
|
|
24
20
|
});
|
|
25
21
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "applesauce-signers",
|
|
3
|
-
"version": "0.0.0-next-
|
|
3
|
+
"version": "0.0.0-next-20250323173930",
|
|
4
4
|
"description": "Signer classes for applesauce",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"@noble/hashes": "^1.7.1",
|
|
37
37
|
"@noble/secp256k1": "^1.7.1",
|
|
38
38
|
"@scure/base": "^1.2.4",
|
|
39
|
-
"applesauce-core": "0.
|
|
39
|
+
"applesauce-core": "^0.12.0",
|
|
40
40
|
"debug": "^4.4.0",
|
|
41
41
|
"nanoid": "^5.0.9",
|
|
42
42
|
"nostr-tools": "^2.10.4"
|