applesauce-signers 0.0.0-next-20250429163257 → 0.0.0-next-20250511152752
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/README.md +1 -1
- package/dist/__tests__/exports.test.d.ts +1 -0
- package/dist/__tests__/exports.test.js +22 -0
- package/dist/helpers/__tests__/exports.test.d.ts +1 -0
- package/dist/helpers/__tests__/exports.test.js +11 -0
- package/dist/signers/__tests__/exports.test.d.ts +1 -0
- package/dist/signers/__tests__/exports.test.js +21 -0
- package/dist/signers/__tests__/nostr-connect-signer.test.d.ts +1 -0
- package/dist/signers/__tests__/nostr-connect-signer.test.js +66 -0
- package/dist/signers/nostr-connect-signer.d.ts +4 -3
- package/dist/signers/nostr-connect-signer.js +21 -6
- package/dist/signers/serial-port-signer.d.ts +1 -1
- package/dist/signers/serial-port-signer.js +4 -4
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ For detailed documentation and API reference, see:
|
|
|
8
8
|
|
|
9
9
|
- [Signers Documentation](https://hzrd149.github.io/applesauce/signers/signers.html)
|
|
10
10
|
- [Nostr Connect Documentation](https://hzrd149.github.io/applesauce/signers/nostr-connect.html)
|
|
11
|
-
- [API Reference](https://hzrd149.github.io/applesauce/typedoc/modules/
|
|
11
|
+
- [API Reference](https://hzrd149.github.io/applesauce/typedoc/modules/applesauce-signers.html)
|
|
12
12
|
|
|
13
13
|
## Available Signers
|
|
14
14
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import * as exports from "../index.js";
|
|
3
|
+
describe("exports", () => {
|
|
4
|
+
it("should export the expected functions", () => {
|
|
5
|
+
expect(Object.keys(exports).sort()).toMatchInlineSnapshot(`
|
|
6
|
+
[
|
|
7
|
+
"AmberClipboardSigner",
|
|
8
|
+
"ExtensionMissingError",
|
|
9
|
+
"ExtensionSigner",
|
|
10
|
+
"Helpers",
|
|
11
|
+
"NostrConnectMethod",
|
|
12
|
+
"NostrConnectSigner",
|
|
13
|
+
"PasswordSigner",
|
|
14
|
+
"Permission",
|
|
15
|
+
"ReadonlySigner",
|
|
16
|
+
"SerialPortSigner",
|
|
17
|
+
"SimpleSigner",
|
|
18
|
+
"isErrorResponse",
|
|
19
|
+
]
|
|
20
|
+
`);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import * as exports from "../index.js";
|
|
3
|
+
describe("exports", () => {
|
|
4
|
+
it("should export the expected functions", () => {
|
|
5
|
+
expect(Object.keys(exports).sort()).toMatchInlineSnapshot(`
|
|
6
|
+
[
|
|
7
|
+
"isNIP04",
|
|
8
|
+
]
|
|
9
|
+
`);
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import * as exports from "../index.js";
|
|
3
|
+
describe("exports", () => {
|
|
4
|
+
it("should export the expected functions", () => {
|
|
5
|
+
expect(Object.keys(exports).sort()).toMatchInlineSnapshot(`
|
|
6
|
+
[
|
|
7
|
+
"AmberClipboardSigner",
|
|
8
|
+
"ExtensionMissingError",
|
|
9
|
+
"ExtensionSigner",
|
|
10
|
+
"NostrConnectMethod",
|
|
11
|
+
"NostrConnectSigner",
|
|
12
|
+
"PasswordSigner",
|
|
13
|
+
"Permission",
|
|
14
|
+
"ReadonlySigner",
|
|
15
|
+
"SerialPortSigner",
|
|
16
|
+
"SimpleSigner",
|
|
17
|
+
"isErrorResponse",
|
|
18
|
+
]
|
|
19
|
+
`);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { NostrConnectSigner } from "../nostr-connect-signer.js";
|
|
3
|
+
import { SimpleSigner } from "../simple-signer.js";
|
|
4
|
+
const relays = ["wss://relay.signer.com"];
|
|
5
|
+
const client = new SimpleSigner();
|
|
6
|
+
const remote = new SimpleSigner();
|
|
7
|
+
const observable = { unsubscribe: vi.fn() };
|
|
8
|
+
const req = { subscribe: vi.fn().mockReturnValue(observable) };
|
|
9
|
+
const subscriptionMethod = vi.fn().mockReturnValue(req);
|
|
10
|
+
const publishMethod = vi.fn(async () => { });
|
|
11
|
+
let signer;
|
|
12
|
+
beforeEach(async () => {
|
|
13
|
+
observable.unsubscribe.mockClear();
|
|
14
|
+
req.subscribe.mockClear();
|
|
15
|
+
subscriptionMethod.mockClear();
|
|
16
|
+
publishMethod.mockClear();
|
|
17
|
+
signer = new NostrConnectSigner({
|
|
18
|
+
relays,
|
|
19
|
+
remote: await remote.getPublicKey(),
|
|
20
|
+
signer: client,
|
|
21
|
+
subscriptionMethod,
|
|
22
|
+
publishMethod,
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
describe("connection", () => {
|
|
26
|
+
it("should call subscription method with filters", async () => {
|
|
27
|
+
signer.connect();
|
|
28
|
+
expect(subscriptionMethod).toHaveBeenCalledWith(relays, [{ "#p": [await client.getPublicKey()], kinds: [24133] }]);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
describe("open", () => {
|
|
32
|
+
it("should call subscription method with filters", async () => {
|
|
33
|
+
signer.open();
|
|
34
|
+
expect(subscriptionMethod).toHaveBeenCalledWith(relays, [{ "#p": [await client.getPublicKey()], kinds: [24133] }]);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
describe("waitForSigner", () => {
|
|
38
|
+
it("should accept an abort signal", async () => {
|
|
39
|
+
const signer = new NostrConnectSigner({
|
|
40
|
+
relays: ["wss://relay.signer.com"],
|
|
41
|
+
signer: client,
|
|
42
|
+
subscriptionMethod,
|
|
43
|
+
publishMethod,
|
|
44
|
+
});
|
|
45
|
+
const controller = new AbortController();
|
|
46
|
+
const p = signer.waitForSigner(controller.signal);
|
|
47
|
+
setTimeout(() => {
|
|
48
|
+
controller.abort();
|
|
49
|
+
}, 10);
|
|
50
|
+
await expect(p).rejects.toThrow("Aborted");
|
|
51
|
+
expect(signer.listening).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
describe("close", () => {
|
|
55
|
+
it("should close the connection", async () => {
|
|
56
|
+
await signer.open();
|
|
57
|
+
expect(req.subscribe).toHaveBeenCalled();
|
|
58
|
+
await signer.close();
|
|
59
|
+
expect(observable.unsubscribe).toHaveBeenCalled();
|
|
60
|
+
});
|
|
61
|
+
it("it should cancel waiting for signer promie", async () => {
|
|
62
|
+
const p = signer.waitForSigner();
|
|
63
|
+
await signer.close();
|
|
64
|
+
await expect(p).rejects.toThrow("Closed");
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -83,7 +83,7 @@ type Subscribable<T extends unknown> = {
|
|
|
83
83
|
subscribe: (observer: Partial<Observer<T>>) => Unsubscribable;
|
|
84
84
|
};
|
|
85
85
|
export type NostrSubscriptionMethod = (relays: string[], filters: Filter[]) => Subscribable<NostrEvent>;
|
|
86
|
-
export type NostrPublishMethod = (relays: string[], event: NostrEvent) =>
|
|
86
|
+
export type NostrPublishMethod = (relays: string[], event: NostrEvent) => any | Promise<any>;
|
|
87
87
|
export type NostrConnectAppMetadata = {
|
|
88
88
|
name?: string;
|
|
89
89
|
image?: string;
|
|
@@ -98,7 +98,8 @@ export declare class NostrConnectSigner implements Nip07Interface {
|
|
|
98
98
|
protected log: import("debug").Debugger;
|
|
99
99
|
/** The local client signer */
|
|
100
100
|
signer: SimpleSigner;
|
|
101
|
-
|
|
101
|
+
/** Whether the signer is listening for events */
|
|
102
|
+
listening: boolean;
|
|
102
103
|
/** Whether the signer is connected to the remote signer */
|
|
103
104
|
isConnected: boolean;
|
|
104
105
|
/** The users pubkey */
|
|
@@ -143,7 +144,7 @@ export declare class NostrConnectSigner implements Nip07Interface {
|
|
|
143
144
|
connect(secret?: string | undefined, permissions?: string[]): Promise<"ack">;
|
|
144
145
|
private waitingPromise;
|
|
145
146
|
/** Wait for a remote signer to connect */
|
|
146
|
-
waitForSigner(): Promise<void>;
|
|
147
|
+
waitForSigner(abort?: AbortSignal): Promise<void>;
|
|
147
148
|
/** Request to create an account on the remote signer */
|
|
148
149
|
createAccount(username: string, domain: string, email?: string, permissions?: string[]): Promise<string>;
|
|
149
150
|
/** Ensure the signer is connected to the remote signer */
|
|
@@ -40,7 +40,8 @@ export class NostrConnectSigner {
|
|
|
40
40
|
log = logger.extend("NostrConnectSigner");
|
|
41
41
|
/** The local client signer */
|
|
42
42
|
signer;
|
|
43
|
-
|
|
43
|
+
/** Whether the signer is listening for events */
|
|
44
|
+
listening = false;
|
|
44
45
|
/** Whether the signer is connected to the remote signer */
|
|
45
46
|
isConnected = false;
|
|
46
47
|
/** The users pubkey */
|
|
@@ -92,9 +93,9 @@ export class NostrConnectSigner {
|
|
|
92
93
|
req;
|
|
93
94
|
/** Open the connection */
|
|
94
95
|
async open() {
|
|
95
|
-
if (this.
|
|
96
|
+
if (this.listening)
|
|
96
97
|
return;
|
|
97
|
-
this.
|
|
98
|
+
this.listening = true;
|
|
98
99
|
const pubkey = await this.signer.getPublicKey();
|
|
99
100
|
// Setup subscription
|
|
100
101
|
this.req = this.subscriptionMethod(this.relays, [
|
|
@@ -109,9 +110,18 @@ export class NostrConnectSigner {
|
|
|
109
110
|
}
|
|
110
111
|
/** Close the connection */
|
|
111
112
|
async close() {
|
|
112
|
-
this.
|
|
113
|
+
this.listening = false;
|
|
113
114
|
this.isConnected = false;
|
|
114
|
-
|
|
115
|
+
// Close the current subscription
|
|
116
|
+
if (this.req) {
|
|
117
|
+
this.req.unsubscribe();
|
|
118
|
+
this.req = undefined;
|
|
119
|
+
}
|
|
120
|
+
// Cancel waiting promise
|
|
121
|
+
if (this.waitingPromise) {
|
|
122
|
+
this.waitingPromise.reject(new Error("Closed"));
|
|
123
|
+
this.waitingPromise = null;
|
|
124
|
+
}
|
|
115
125
|
this.log("Closed");
|
|
116
126
|
}
|
|
117
127
|
requests = new Map();
|
|
@@ -216,11 +226,16 @@ export class NostrConnectSigner {
|
|
|
216
226
|
}
|
|
217
227
|
waitingPromise = null;
|
|
218
228
|
/** Wait for a remote signer to connect */
|
|
219
|
-
waitForSigner() {
|
|
229
|
+
waitForSigner(abort) {
|
|
220
230
|
if (this.isConnected)
|
|
221
231
|
return Promise.resolve();
|
|
222
232
|
this.open();
|
|
223
233
|
this.waitingPromise = createDefer();
|
|
234
|
+
abort?.addEventListener("abort", () => {
|
|
235
|
+
this.waitingPromise?.reject(new Error("Aborted"));
|
|
236
|
+
this.waitingPromise = null;
|
|
237
|
+
this.close();
|
|
238
|
+
}, true);
|
|
224
239
|
return this.waitingPromise;
|
|
225
240
|
}
|
|
226
241
|
/** Request to create an account on the remote signer */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { EventTemplate, verifyEvent } from "nostr-tools";
|
|
2
1
|
import { Deferred } from "applesauce-core/promise";
|
|
2
|
+
import { EventTemplate, verifyEvent } from "nostr-tools";
|
|
3
3
|
import { Nip07Interface } from "../nip-07.js";
|
|
4
4
|
type Callback = () => void;
|
|
5
5
|
type DeviceOpts = {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/// <reference types="@types/dom-serial" />
|
|
2
|
-
import {
|
|
3
|
-
import { base64 } from "@scure/base";
|
|
4
|
-
import { randomBytes, hexToBytes, bytesToHex } from "@noble/hashes/utils";
|
|
2
|
+
import { bytesToHex, hexToBytes, randomBytes } from "@noble/hashes/utils";
|
|
5
3
|
import { Point } from "@noble/secp256k1";
|
|
4
|
+
import { base64 } from "@scure/base";
|
|
5
|
+
import { logger } from "applesauce-core";
|
|
6
6
|
import { createDefer } from "applesauce-core/promise";
|
|
7
|
-
import {
|
|
7
|
+
import { getEventHash, verifyEvent } from "nostr-tools";
|
|
8
8
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
9
9
|
function xOnlyToXY(p) {
|
|
10
10
|
return Point.fromHex(p).toHex().substring(2);
|
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-20250511152752",
|
|
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.0.0-next-
|
|
39
|
+
"applesauce-core": "0.0.0-next-20250511152752",
|
|
40
40
|
"debug": "^4.4.0",
|
|
41
41
|
"nanoid": "^5.0.9",
|
|
42
42
|
"nostr-tools": "^2.10.4"
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@types/debug": "^4.1.12",
|
|
46
46
|
"@types/dom-serial": "^1.0.6",
|
|
47
47
|
"typescript": "^5.8.3",
|
|
48
|
-
"vitest": "^3.1.
|
|
48
|
+
"vitest": "^3.1.3"
|
|
49
49
|
},
|
|
50
50
|
"funding": {
|
|
51
51
|
"type": "lightning",
|