applesauce-signers 0.0.0-next-20250315140539 → 0.0.0-next-20250323180355
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,26 @@ 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>;
|
|
69
|
+
/** A method for subscribing to relays */
|
|
70
|
+
subscriptionMethod?: NostrSubscriptionMethod;
|
|
71
|
+
/** A method for publishing events */
|
|
72
|
+
publishMethod?: NostrPublishMethod;
|
|
73
|
+
};
|
|
74
|
+
interface Unsubscribable {
|
|
75
|
+
unsubscribe(): void;
|
|
76
|
+
}
|
|
77
|
+
interface Observer<T> {
|
|
78
|
+
next: (value: T) => void;
|
|
79
|
+
error: (err: any) => void;
|
|
80
|
+
complete: () => void;
|
|
81
|
+
}
|
|
82
|
+
type Subscribable<T extends unknown> = {
|
|
83
|
+
subscribe: (observer: Partial<Observer<T>>) => Unsubscribable;
|
|
77
84
|
};
|
|
85
|
+
export type NostrSubscriptionMethod = (filters: Filter[], relays: string[]) => Subscribable<NostrEvent>;
|
|
86
|
+
export type NostrPublishMethod = (event: NostrEvent, relays: string[]) => void | Promise<void>;
|
|
78
87
|
export type NostrConnectAppMetadata = {
|
|
79
88
|
name?: string;
|
|
80
89
|
image?: string;
|
|
@@ -82,12 +91,10 @@ export type NostrConnectAppMetadata = {
|
|
|
82
91
|
permissions?: string[];
|
|
83
92
|
};
|
|
84
93
|
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
94
|
/** A method that is called when an event needs to be published */
|
|
90
|
-
|
|
95
|
+
protected publishMethod: NostrPublishMethod;
|
|
96
|
+
/** The active nostr subscription */
|
|
97
|
+
protected subscriptionMethod: NostrSubscriptionMethod;
|
|
91
98
|
protected log: import("debug").Debugger;
|
|
92
99
|
/** The local client signer */
|
|
93
100
|
signer: SimpleSigner;
|
|
@@ -102,6 +109,7 @@ export declare class NostrConnectSigner implements Nip07Interface {
|
|
|
102
109
|
remote?: string;
|
|
103
110
|
/** Client pubkey */
|
|
104
111
|
get clientPubkey(): string;
|
|
112
|
+
/** A method for handling "auth" requests */
|
|
105
113
|
onAuth: (url: string) => Promise<void>;
|
|
106
114
|
verifyEvent: typeof verifyEvent;
|
|
107
115
|
/** A secret used when initiating a connection from the client side */
|
|
@@ -114,7 +122,11 @@ export declare class NostrConnectSigner implements Nip07Interface {
|
|
|
114
122
|
encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
|
|
115
123
|
decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
|
|
116
124
|
} | undefined;
|
|
117
|
-
|
|
125
|
+
static subscriptionMethod: NostrSubscriptionMethod | undefined;
|
|
126
|
+
static publishMethod: NostrPublishMethod | undefined;
|
|
127
|
+
constructor(opts: NostrConnectSignerOptions);
|
|
128
|
+
/** The currently active REQ subscription */
|
|
129
|
+
protected req?: Unsubscribable;
|
|
118
130
|
/** Open the connection */
|
|
119
131
|
open(): Promise<void>;
|
|
120
132
|
/** Close the connection */
|
|
@@ -155,7 +167,7 @@ export declare class NostrConnectSigner implements Nip07Interface {
|
|
|
155
167
|
/** Builds an array of signing permissions for event kinds */
|
|
156
168
|
static buildSigningPermissions(kinds: number[]): string[];
|
|
157
169
|
/** Create a {@link NostrConnectSigner} from a bunker:// URI */
|
|
158
|
-
static fromBunkerURI(uri: string, options:
|
|
170
|
+
static fromBunkerURI(uri: string, options: Omit<NostrConnectSignerOptions, "relays"> & {
|
|
159
171
|
permissions?: string[];
|
|
160
172
|
signer?: SimpleSigner;
|
|
161
173
|
}): 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
|
+
publishMethod;
|
|
38
|
+
/** The active nostr subscription */
|
|
39
|
+
subscriptionMethod;
|
|
44
40
|
log = logger.extend("NostrConnectSigner");
|
|
45
41
|
/** The local client signer */
|
|
46
42
|
signer;
|
|
@@ -57,19 +53,27 @@ 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;
|
|
63
|
+
static subscriptionMethod = undefined;
|
|
64
|
+
static publishMethod = undefined;
|
|
66
65
|
constructor(opts) {
|
|
67
66
|
this.relays = opts.relays;
|
|
68
67
|
this.pubkey = opts.pubkey;
|
|
69
68
|
this.remote = opts.remote;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
const subscriptionMethod = opts.subscriptionMethod || NostrConnectSigner.subscriptionMethod;
|
|
70
|
+
if (!subscriptionMethod)
|
|
71
|
+
throw new Error("Missing subscriptionMethod, either pass a method or set NostrConnectSigner.subscriptionMethod");
|
|
72
|
+
const publishMethod = opts.publishMethod || NostrConnectSigner.publishMethod;
|
|
73
|
+
if (!publishMethod)
|
|
74
|
+
throw new Error("Missing publishMethod, either pass a method or set NostrConnectSigner.publishMethod");
|
|
75
|
+
this.subscriptionMethod = subscriptionMethod;
|
|
76
|
+
this.publishMethod = publishMethod;
|
|
73
77
|
if (opts.onAuth)
|
|
74
78
|
this.onAuth = opts.onAuth;
|
|
75
79
|
this.signer = opts?.signer || new SimpleSigner();
|
|
@@ -82,6 +86,8 @@ export class NostrConnectSigner {
|
|
|
82
86
|
decrypt: this.nip44Decrypt.bind(this),
|
|
83
87
|
};
|
|
84
88
|
}
|
|
89
|
+
/** The currently active REQ subscription */
|
|
90
|
+
req;
|
|
85
91
|
/** Open the connection */
|
|
86
92
|
async open() {
|
|
87
93
|
if (this.subscriptionOpen)
|
|
@@ -89,19 +95,21 @@ export class NostrConnectSigner {
|
|
|
89
95
|
this.subscriptionOpen = true;
|
|
90
96
|
const pubkey = await this.signer.getPublicKey();
|
|
91
97
|
// Setup subscription
|
|
92
|
-
|
|
98
|
+
this.req = this.subscriptionMethod([
|
|
93
99
|
{
|
|
94
100
|
kinds: [kinds.NostrConnect],
|
|
95
101
|
"#p": [pubkey],
|
|
96
102
|
},
|
|
97
|
-
], this.relays
|
|
103
|
+
], this.relays).subscribe({
|
|
104
|
+
next: (event) => this.handleEvent(event),
|
|
105
|
+
});
|
|
98
106
|
this.log("Opened", this.relays);
|
|
99
107
|
}
|
|
100
108
|
/** Close the connection */
|
|
101
109
|
async close() {
|
|
102
110
|
this.subscriptionOpen = false;
|
|
103
111
|
this.isConnected = false;
|
|
104
|
-
|
|
112
|
+
this.req?.unsubscribe();
|
|
105
113
|
this.log("Closed");
|
|
106
114
|
}
|
|
107
115
|
requests = new Map();
|
|
@@ -178,7 +186,7 @@ export class NostrConnectSigner {
|
|
|
178
186
|
this.log(`Sending request ${id} (${method}) ${JSON.stringify(params)}`);
|
|
179
187
|
const p = createDefer();
|
|
180
188
|
this.requests.set(id, p);
|
|
181
|
-
await this.
|
|
189
|
+
await this.publishMethod?.(event, this.relays);
|
|
182
190
|
return p;
|
|
183
191
|
}
|
|
184
192
|
/** Connect to remote signer */
|
|
@@ -3,23 +3,21 @@ 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
12
|
const signer = new NostrConnectSigner({
|
|
14
|
-
onSubOpen,
|
|
15
|
-
onSubClose,
|
|
16
|
-
onPublishEvent,
|
|
17
13
|
relays,
|
|
18
14
|
remote: await remote.getPublicKey(),
|
|
19
15
|
signer: client,
|
|
16
|
+
subscriptionMethod: subscription,
|
|
17
|
+
publishMethod: publish,
|
|
20
18
|
});
|
|
21
19
|
signer.connect();
|
|
22
|
-
expect(
|
|
20
|
+
expect(subscription).toHaveBeenCalledWith([{ "#p": [await client.getPublicKey()], kinds: [24133] }], relays);
|
|
23
21
|
});
|
|
24
22
|
});
|
|
25
23
|
});
|
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-20250323180355",
|
|
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"
|