divine-signer 0.3.1 → 0.4.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/bunker-signer.d.ts +18 -6
- package/dist/bunker-signer.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +45 -20
- package/package.json +1 -1
package/dist/bunker-signer.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { type BunkerSignerParams } from 'nostr-tools/nip46';
|
|
2
2
|
import type { EventTemplate, VerifiedEvent } from 'nostr-tools/pure';
|
|
3
3
|
import type { NostrSigner, SignerType } from './types';
|
|
4
|
+
export interface NostrConnectHandle {
|
|
5
|
+
/** Call after showing the QR code. Resolves when the remote signer acks. */
|
|
6
|
+
waitForSigner(): Promise<BunkerNIP44Signer>;
|
|
7
|
+
/** Abort the connection attempt. */
|
|
8
|
+
abort(): void;
|
|
9
|
+
}
|
|
4
10
|
export declare class BunkerNIP44Signer implements NostrSigner {
|
|
5
11
|
readonly type: SignerType;
|
|
6
12
|
private readonly inner;
|
|
@@ -11,17 +17,23 @@ export declare class BunkerNIP44Signer implements NostrSigner {
|
|
|
11
17
|
*
|
|
12
18
|
* Unlike fromBunkerUrl(), this does NOT send a `connect` RPC — the session
|
|
13
19
|
* already exists on the remote signer. It sets up the relay subscription
|
|
14
|
-
* and
|
|
20
|
+
* and calls getPublicKey() to verify the channel is alive (and prime the cache).
|
|
15
21
|
*/
|
|
16
22
|
static reconnect(clientSecretKey: Uint8Array, bunkerUrl: string, params?: BunkerSignerParams, connectTimeout?: number): Promise<BunkerNIP44Signer>;
|
|
23
|
+
/**
|
|
24
|
+
* Two-phase nostrconnect: sets up relay connections and subscription,
|
|
25
|
+
* then returns a handle. Show the QR code, then call handle.waitForSigner().
|
|
26
|
+
*
|
|
27
|
+
* This avoids a race where the user scans before the subscription is live.
|
|
28
|
+
*/
|
|
29
|
+
static prepareNostrConnect(connectionURI: string, clientSecretKey: Uint8Array, params?: BunkerSignerParams, timeoutOrAbort?: number | AbortSignal): Promise<NostrConnectHandle>;
|
|
17
30
|
/**
|
|
18
31
|
* Connect via a nostrconnect:// URI (QR code flow).
|
|
19
32
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* the signer via BunkerSigner.fromBunker which skips switch_relays.
|
|
33
|
+
* Convenience wrapper around prepareNostrConnect() — connects to relays,
|
|
34
|
+
* subscribes, and waits for the ack in one call. If you need to show a
|
|
35
|
+
* QR code only after the subscription is live, use prepareNostrConnect()
|
|
36
|
+
* instead.
|
|
25
37
|
*/
|
|
26
38
|
static fromNostrConnect(connectionURI: string, clientSecretKey: Uint8Array, params?: BunkerSignerParams, timeoutOrAbort?: number | AbortSignal): Promise<BunkerNIP44Signer>;
|
|
27
39
|
getPublicKey(): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bunker-signer.d.ts","sourceRoot":"","sources":["../src/bunker-signer.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAI3B,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEvD,qBAAa,iBAAkB,YAAW,WAAW;IACnD,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC,OAAO;IAKP,wDAAwD;WAC3C,aAAa,CACxB,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,kBAAkB,EAC3B,YAAY,CAAC,EAAE,UAAU,EACzB,cAAc,SAAS,GACtB,OAAO,CAAC,iBAAiB,CAAC;IAgB7B;;;;;OAKG;WACU,SAAS,CACpB,eAAe,EAAE,UAAU,EAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,kBAAkB,EAC3B,cAAc,SAAS,GACtB,OAAO,CAAC,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"bunker-signer.d.ts","sourceRoot":"","sources":["../src/bunker-signer.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAI3B,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEvD,MAAM,WAAW,kBAAkB;IACjC,4EAA4E;IAC5E,aAAa,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC5C,oCAAoC;IACpC,KAAK,IAAI,IAAI,CAAC;CACf;AAED,qBAAa,iBAAkB,YAAW,WAAW;IACnD,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC,OAAO;IAKP,wDAAwD;WAC3C,aAAa,CACxB,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,kBAAkB,EAC3B,YAAY,CAAC,EAAE,UAAU,EACzB,cAAc,SAAS,GACtB,OAAO,CAAC,iBAAiB,CAAC;IAgB7B;;;;;OAKG;WACU,SAAS,CACpB,eAAe,EAAE,UAAU,EAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,kBAAkB,EAC3B,cAAc,SAAS,GACtB,OAAO,CAAC,iBAAiB,CAAC;IAoB7B;;;;;OAKG;WACU,mBAAmB,CAC9B,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,UAAU,EAC3B,MAAM,CAAC,EAAE,kBAAkB,EAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,WAAW,GACpC,OAAO,CAAC,kBAAkB,CAAC;IA2F9B;;;;;;;OAOG;WACU,gBAAgB,CAC3B,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,UAAU,EAC3B,MAAM,CAAC,EAAE,kBAAkB,EAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,WAAW,GACpC,OAAO,CAAC,iBAAiB,CAAC;IAUvB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAW/B,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAIvD,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIhE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIjE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIhE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIvE,YAAY,IAAI,MAAM;IAIhB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export type { TokenRefreshResult } from './oauth-signer';
|
|
|
5
5
|
export { NsecSigner } from './nsec-signer';
|
|
6
6
|
export { ExtensionSigner } from './extension-signer';
|
|
7
7
|
export { BunkerNIP44Signer } from './bunker-signer';
|
|
8
|
+
export type { NostrConnectHandle } from './bunker-signer';
|
|
8
9
|
export { OAuthSigner, OAuthError } from './oauth-signer';
|
|
9
10
|
export { createSessionStore, restoreSession } from './session';
|
|
10
11
|
export { buildOAuthUrl, exchangeCode } from './oauth';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACvD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC7E,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtE,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGzD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGzD,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG/D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACvD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC7E,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtE,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGzD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGzD,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG/D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -112,7 +112,7 @@ var BunkerNIP44Signer = class _BunkerNIP44Signer {
|
|
|
112
112
|
*
|
|
113
113
|
* Unlike fromBunkerUrl(), this does NOT send a `connect` RPC — the session
|
|
114
114
|
* already exists on the remote signer. It sets up the relay subscription
|
|
115
|
-
* and
|
|
115
|
+
* and calls getPublicKey() to verify the channel is alive (and prime the cache).
|
|
116
116
|
*/
|
|
117
117
|
static async reconnect(clientSecretKey, bunkerUrl, params, connectTimeout = 3e4) {
|
|
118
118
|
const bp = await parseBunkerInput(bunkerUrl);
|
|
@@ -121,7 +121,7 @@ var BunkerNIP44Signer = class _BunkerNIP44Signer {
|
|
|
121
121
|
}
|
|
122
122
|
const inner = BunkerSigner.fromBunker(clientSecretKey, bp, params);
|
|
123
123
|
await Promise.race([
|
|
124
|
-
inner.
|
|
124
|
+
inner.getPublicKey(),
|
|
125
125
|
new Promise(
|
|
126
126
|
(_, reject) => setTimeout(() => reject(new Error("Bunker reconnection timed out")), connectTimeout)
|
|
127
127
|
)
|
|
@@ -129,15 +129,12 @@ var BunkerNIP44Signer = class _BunkerNIP44Signer {
|
|
|
129
129
|
return new _BunkerNIP44Signer(inner, "nostrconnect");
|
|
130
130
|
}
|
|
131
131
|
/**
|
|
132
|
-
*
|
|
132
|
+
* Two-phase nostrconnect: sets up relay connections and subscription,
|
|
133
|
+
* then returns a handle. Show the QR code, then call handle.waitForSigner().
|
|
133
134
|
*
|
|
134
|
-
*
|
|
135
|
-
* BunkerSigner.fromURI, which sends a `switch_relays` RPC that
|
|
136
|
-
* signers like Primal don't understand (causing a parse error and
|
|
137
|
-
* potentially disrupting the session). After the handshake we create
|
|
138
|
-
* the signer via BunkerSigner.fromBunker which skips switch_relays.
|
|
135
|
+
* This avoids a race where the user scans before the subscription is live.
|
|
139
136
|
*/
|
|
140
|
-
static async
|
|
137
|
+
static async prepareNostrConnect(connectionURI, clientSecretKey, params, timeoutOrAbort) {
|
|
141
138
|
const uri = new URL(connectionURI);
|
|
142
139
|
const relays = uri.searchParams.getAll("relay");
|
|
143
140
|
const secret = uri.searchParams.get("secret");
|
|
@@ -146,13 +143,16 @@ var BunkerNIP44Signer = class _BunkerNIP44Signer {
|
|
|
146
143
|
throw new Error("No relays specified in nostrconnect URI");
|
|
147
144
|
}
|
|
148
145
|
const abort = typeof timeoutOrAbort === "number" ? AbortSignal.timeout(timeoutOrAbort) : timeoutOrAbort;
|
|
146
|
+
const ac = new AbortController();
|
|
147
|
+
const effectiveAbort = abort ?? ac.signal;
|
|
149
148
|
const pool = new SimplePool();
|
|
150
|
-
|
|
151
|
-
|
|
149
|
+
await Promise.all(relays.map((r) => pool.ensureRelay(r)));
|
|
150
|
+
let settled = false;
|
|
151
|
+
const signerPromise = new Promise((resolve, reject) => {
|
|
152
|
+
if (effectiveAbort.aborted) {
|
|
152
153
|
reject(new Error("Aborted"));
|
|
153
154
|
return;
|
|
154
155
|
}
|
|
155
|
-
let settled = false;
|
|
156
156
|
const sub = pool.subscribe(
|
|
157
157
|
relays,
|
|
158
158
|
{ kinds: [24133], "#p": [clientPubkey], limit: 0 },
|
|
@@ -179,10 +179,10 @@ var BunkerNIP44Signer = class _BunkerNIP44Signer {
|
|
|
179
179
|
);
|
|
180
180
|
}
|
|
181
181
|
},
|
|
182
|
-
abort
|
|
182
|
+
abort: effectiveAbort
|
|
183
183
|
}
|
|
184
184
|
);
|
|
185
|
-
|
|
185
|
+
effectiveAbort.addEventListener(
|
|
186
186
|
"abort",
|
|
187
187
|
() => {
|
|
188
188
|
if (!settled) {
|
|
@@ -194,12 +194,37 @@ var BunkerNIP44Signer = class _BunkerNIP44Signer {
|
|
|
194
194
|
{ once: true }
|
|
195
195
|
);
|
|
196
196
|
});
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
197
|
+
return {
|
|
198
|
+
async waitForSigner() {
|
|
199
|
+
const signerPubkey = await signerPromise;
|
|
200
|
+
const bp = { pubkey: signerPubkey, relays, secret: secret || "" };
|
|
201
|
+
const inner = BunkerSigner.fromBunker(clientSecretKey, bp, {
|
|
202
|
+
...params,
|
|
203
|
+
pool
|
|
204
|
+
});
|
|
205
|
+
return new _BunkerNIP44Signer(inner, "nostrconnect");
|
|
206
|
+
},
|
|
207
|
+
abort() {
|
|
208
|
+
ac.abort();
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Connect via a nostrconnect:// URI (QR code flow).
|
|
214
|
+
*
|
|
215
|
+
* Convenience wrapper around prepareNostrConnect() — connects to relays,
|
|
216
|
+
* subscribes, and waits for the ack in one call. If you need to show a
|
|
217
|
+
* QR code only after the subscription is live, use prepareNostrConnect()
|
|
218
|
+
* instead.
|
|
219
|
+
*/
|
|
220
|
+
static async fromNostrConnect(connectionURI, clientSecretKey, params, timeoutOrAbort) {
|
|
221
|
+
const handle = await _BunkerNIP44Signer.prepareNostrConnect(
|
|
222
|
+
connectionURI,
|
|
223
|
+
clientSecretKey,
|
|
224
|
+
params,
|
|
225
|
+
timeoutOrAbort
|
|
226
|
+
);
|
|
227
|
+
return handle.waitForSigner();
|
|
203
228
|
}
|
|
204
229
|
async getPublicKey() {
|
|
205
230
|
return Promise.race([
|