signet-login 0.10.1 → 0.10.3
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 +30 -5
- package/dist/modal.js +41 -18
- package/dist/signers.d.ts +17 -5
- package/dist/signers.js +51 -6
- package/dist/signet-login.d.ts +2 -2
- package/dist/signet-login.iife.js +16 -16
- package/dist/signet-login.js +6 -2
- package/dist/types.d.ts +7 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,8 @@ Published as `signet-login`.
|
|
|
6
6
|
|
|
7
7
|
**Signet Access** is a drop-in auth and signer-access SDK for Nostr-aware websites. One picker, one session shape, multiple ways to prove identity and, when available, keep a live signer:
|
|
8
8
|
|
|
9
|
-
- **
|
|
9
|
+
- **Local Signet** on this device, against hosted or local-dev Signet
|
|
10
|
+
- **Remote Signet** by cross-device QR, so a phone or second machine can approve
|
|
10
11
|
- **Browser extension** via NIP-07 (bark, Alby, nos2x, Flamingo, ...)
|
|
11
12
|
- **Connect a Nostr signer** via app-initiated NIP-46 / NostrConnect
|
|
12
13
|
- **Paste or scan bunker URI** for Heartwood, nsecBunker, Amber, or compatible signers
|
|
@@ -88,8 +89,10 @@ interface SignetStorage {
|
|
|
88
89
|
|
|
89
90
|
type LoginPickerMethod =
|
|
90
91
|
| 'nip07'
|
|
91
|
-
| '
|
|
92
|
-
| '
|
|
92
|
+
| 'local-signet' // same-device Signet, relay delivery
|
|
93
|
+
| 'remote-signet' // cross-device Signet QR
|
|
94
|
+
| 'redirect' // legacy alias for local-signet
|
|
95
|
+
| 'qr' // legacy alias for remote-signet
|
|
93
96
|
| 'bunker' // paste bunker://
|
|
94
97
|
| 'nostrconnect' // show nostrconnect:// QR
|
|
95
98
|
| 'amber' // Android NIP-55
|
|
@@ -110,7 +113,14 @@ By default, the picker shows ordinary user-facing methods first and groups `bunk
|
|
|
110
113
|
```js
|
|
111
114
|
await Signet.login({
|
|
112
115
|
appName: 'My Game',
|
|
113
|
-
methods: ['
|
|
116
|
+
methods: ['local-signet', 'remote-signet', 'nip07'],
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
await Signet.login({
|
|
120
|
+
appName: 'My Local Dev Game',
|
|
121
|
+
preferredMethod: 'local-signet',
|
|
122
|
+
signetAppOrigin: 'http://localhost:5174',
|
|
123
|
+
relayUrl: 'ws://localhost:7777',
|
|
114
124
|
});
|
|
115
125
|
|
|
116
126
|
await Signet.login({
|
|
@@ -121,6 +131,8 @@ await Signet.login({
|
|
|
121
131
|
});
|
|
122
132
|
```
|
|
123
133
|
|
|
134
|
+
`redirect` and `qr` remain supported picker aliases for existing apps, but new integrations should use `local-signet` and `remote-signet`.
|
|
135
|
+
|
|
124
136
|
When camera APIs are available, the bunker URI screen can scan `bunker://` QR codes directly. Paste remains the fallback.
|
|
125
137
|
|
|
126
138
|
### Headless/custom UI
|
|
@@ -152,9 +164,22 @@ await fetch('/api/login', {
|
|
|
152
164
|
});
|
|
153
165
|
```
|
|
154
166
|
|
|
155
|
-
Headless exports include `hasNip07`, `createNip07Signer`, `createBunkerSigner`, `createBunkerSignerFromNostrConnect`, `buildNostrConnectUri`, `createLocalSignerFromNsec`, `createLoginAuthEvent`, `createSessionFromSigner`, and `generateSecretKey`.
|
|
167
|
+
Headless exports include `hasNip07`, `createNip07Signer`, `createBunkerSigner`, `createBunkerSignerFromNostrConnect`, `buildNostrConnectUri`, `buildBunkerUriFromNostrConnectUri`, `isBunkerUri`, `isNostrConnectUri`, `isSupportedPairingUri`, `createLocalSignerFromNsec`, `createLoginAuthEvent`, `createSessionFromSigner`, and `generateSecretKey`.
|
|
156
168
|
The IIFE bundle attaches the same helpers to `window.Signet`.
|
|
157
169
|
|
|
170
|
+
### NostrConnect and bunker roles
|
|
171
|
+
|
|
172
|
+
NIP-46 has two URI directions:
|
|
173
|
+
|
|
174
|
+
| URI | Producer | Consumer | Use |
|
|
175
|
+
|---|---|---|---|
|
|
176
|
+
| `nostrconnect://...` | The app / Signet Access client | Signer app scans or opens it | First pairing, where the app advertises its client pubkey, relays, requested permissions, and one-time secret |
|
|
177
|
+
| `bunker://...` | The signer / bunker | App connects to it | Reconnect, paste/scan bunker flows, native clients, and persisted sessions |
|
|
178
|
+
|
|
179
|
+
`createBunkerSignerFromNostrConnect()` waits for the signer response and then stores the equivalent `bunker://` reconnect URI internally, preserving the relay list and secret. This matters for apps such as Canary, Pallasite, and Axenstax: the user can pair once with NostrConnect, then `restoreSession()` can reconnect with the same stable client key instead of showing a fresh pairing request.
|
|
180
|
+
|
|
181
|
+
Signet Access is the app-side session broker. Identity creation, recovery, and derived personas belong in Signet, Heartwood, and `nsec-tree`; app integrations should consume the returned pubkey and capability flags instead of deriving identities inside the login SDK.
|
|
182
|
+
|
|
158
183
|
### Custom storage
|
|
159
184
|
|
|
160
185
|
By default, Signet Access stores session state in localStorage under `signet:login.*`. Pass `storage` when you need encrypted, async, IndexedDB, server-backed, or test storage:
|
package/dist/modal.js
CHANGED
|
@@ -14,7 +14,8 @@ import { bytesToHex } from '@noble/hashes/utils';
|
|
|
14
14
|
import QRCode from 'qrcode';
|
|
15
15
|
import jsQR from 'jsqr';
|
|
16
16
|
const QR_BUNKER_CONNECT_TIMEOUT_MS = 8000;
|
|
17
|
-
const DEFAULT_PICKER_METHODS = ['nip07', 'amber', '
|
|
17
|
+
const DEFAULT_PICKER_METHODS = ['nip07', 'amber', 'local-signet', 'remote-signet', 'bunker', 'nostrconnect', 'nsec'];
|
|
18
|
+
const ALL_PICKER_METHODS = [...DEFAULT_PICKER_METHODS, 'redirect', 'qr'];
|
|
18
19
|
const DEFAULT_ADVANCED_METHODS = ['bunker', 'nostrconnect', 'nsec'];
|
|
19
20
|
const DEFAULT_NOSTR_CONNECT_PERMS = ['sign_event', 'nip44_encrypt', 'nip44_decrypt'];
|
|
20
21
|
function escapeHtml(str) {
|
|
@@ -254,12 +255,28 @@ async function startCameraQrScanner(input) {
|
|
|
254
255
|
const METHOD_META = {
|
|
255
256
|
nip07: { icon: '🌐', title: 'Browser extension', hint: 'bark, Alby, nos2x' },
|
|
256
257
|
amber: { icon: '🤖', title: 'Sign in with Amber', hint: 'Android signer (NIP-55)' },
|
|
257
|
-
|
|
258
|
-
|
|
258
|
+
'local-signet': { icon: '🪪', title: 'Local Signet', hint: 'Open Signet on this device' },
|
|
259
|
+
'remote-signet': { icon: '📱', title: 'Remote Signet', hint: 'Scan with Signet on another device' },
|
|
260
|
+
redirect: { icon: '🪪', title: 'Local Signet', hint: 'Open Signet on this device' },
|
|
261
|
+
qr: { icon: '📱', title: 'Remote Signet', hint: 'Scan with Signet on another device' },
|
|
259
262
|
bunker: { icon: '🔑', title: 'Paste bunker URI', hint: 'For NIP-46 power users' },
|
|
260
263
|
nostrconnect: { icon: '📡', title: 'Connect a Nostr signer', hint: 'Scan with nsec.app, Amber, Keychat...' },
|
|
261
264
|
nsec: { icon: '⚠️', title: 'Paste private key', hint: 'In-memory only - risky, last resort' },
|
|
262
265
|
};
|
|
266
|
+
function pickerMethodKey(method) {
|
|
267
|
+
if (method === 'local-signet' || method === 'redirect')
|
|
268
|
+
return 'local-signet';
|
|
269
|
+
if (method === 'remote-signet' || method === 'qr')
|
|
270
|
+
return 'remote-signet';
|
|
271
|
+
return method;
|
|
272
|
+
}
|
|
273
|
+
function routePickerChoice(choice) {
|
|
274
|
+
if (choice === 'local-signet')
|
|
275
|
+
return 'redirect';
|
|
276
|
+
if (choice === 'remote-signet')
|
|
277
|
+
return 'qr';
|
|
278
|
+
return choice;
|
|
279
|
+
}
|
|
263
280
|
function isMethodAvailable(method) {
|
|
264
281
|
if (method === 'nip07')
|
|
265
282
|
return hasNip07();
|
|
@@ -277,9 +294,9 @@ function renderPicker(refs, opts) {
|
|
|
277
294
|
return new Promise(resolve => {
|
|
278
295
|
let advancedOpen = false;
|
|
279
296
|
const availableMethods = opts.methods.filter(isMethodAvailable);
|
|
280
|
-
const advancedSet = new Set(opts.advancedMethods);
|
|
281
|
-
const primaryMethods = availableMethods.filter(method => !advancedSet.has(method));
|
|
282
|
-
const advancedMethods = availableMethods.filter(method => advancedSet.has(method));
|
|
297
|
+
const advancedSet = new Set(opts.advancedMethods.map(pickerMethodKey));
|
|
298
|
+
const primaryMethods = availableMethods.filter(method => !advancedSet.has(pickerMethodKey(method)));
|
|
299
|
+
const advancedMethods = availableMethods.filter(method => advancedSet.has(pickerMethodKey(method)));
|
|
283
300
|
const attachChoiceHandlers = () => {
|
|
284
301
|
refs.dialog.querySelectorAll('button[data-choice]').forEach(btn => {
|
|
285
302
|
btn.addEventListener('click', () => {
|
|
@@ -806,20 +823,25 @@ async function runNsecFlow(refs, opts) {
|
|
|
806
823
|
}
|
|
807
824
|
function uniquePickerMethods(input, fallback) {
|
|
808
825
|
const source = input ?? fallback;
|
|
809
|
-
const allowed = new Set(
|
|
826
|
+
const allowed = new Set(ALL_PICKER_METHODS);
|
|
827
|
+
const seen = new Set();
|
|
810
828
|
const out = [];
|
|
811
829
|
for (const method of source) {
|
|
812
830
|
if (!allowed.has(method))
|
|
813
831
|
continue;
|
|
814
|
-
|
|
815
|
-
|
|
832
|
+
const key = pickerMethodKey(method);
|
|
833
|
+
if (seen.has(key))
|
|
834
|
+
continue;
|
|
835
|
+
seen.add(key);
|
|
836
|
+
out.push(method);
|
|
816
837
|
}
|
|
817
838
|
return input === undefined && out.length === 0 ? [...fallback] : out;
|
|
818
839
|
}
|
|
819
840
|
function resolveMethodConfig(opts) {
|
|
820
841
|
const methods = uniquePickerMethods(opts.methods, DEFAULT_PICKER_METHODS);
|
|
842
|
+
const methodKeys = new Set(methods.map(pickerMethodKey));
|
|
821
843
|
const advancedMethods = uniquePickerMethods(opts.advancedMethods, DEFAULT_ADVANCED_METHODS)
|
|
822
|
-
.filter(method =>
|
|
844
|
+
.filter(method => methodKeys.has(pickerMethodKey(method)));
|
|
823
845
|
return { methods, advancedMethods };
|
|
824
846
|
}
|
|
825
847
|
function resolveRelayUrls(opts) {
|
|
@@ -895,11 +917,12 @@ async function runLoginModal(opts) {
|
|
|
895
917
|
const choice = resolved.preferredMethod
|
|
896
918
|
? resolved.preferredMethod
|
|
897
919
|
: await Promise.race([renderPicker(refs, resolved), aborted]);
|
|
920
|
+
const routeChoice = choice === null ? null : routePickerChoice(choice);
|
|
898
921
|
if (userAborted)
|
|
899
922
|
return null;
|
|
900
|
-
if (
|
|
923
|
+
if (routeChoice === null || routeChoice === 'cancel')
|
|
901
924
|
return null;
|
|
902
|
-
if (
|
|
925
|
+
if (routeChoice === 'nip07') {
|
|
903
926
|
const result = await Promise.race([runNip07Flow(refs, resolved), aborted]);
|
|
904
927
|
if (userAborted)
|
|
905
928
|
return null;
|
|
@@ -919,7 +942,7 @@ async function runLoginModal(opts) {
|
|
|
919
942
|
authEvent: result.authEvent,
|
|
920
943
|
};
|
|
921
944
|
}
|
|
922
|
-
if (
|
|
945
|
+
if (routeChoice === 'redirect') {
|
|
923
946
|
// Same-device Signet in the modal must keep this app tab alive and keep
|
|
924
947
|
// the My Signet tab alive as the ongoing bunker. Use the relay-backed
|
|
925
948
|
// auth response path here; explicit `login({ mode: 'redirect' })`
|
|
@@ -942,7 +965,7 @@ async function runLoginModal(opts) {
|
|
|
942
965
|
}
|
|
943
966
|
return session;
|
|
944
967
|
}
|
|
945
|
-
if (
|
|
968
|
+
if (routeChoice === 'amber') {
|
|
946
969
|
// Same-tab navigation to a `nostrsigner:` URL. Android dispatches
|
|
947
970
|
// it to Amber; the page comes back via callbackUrl with the signed
|
|
948
971
|
// event in `?event=`. Picked up on next boot by handleRedirectCallback.
|
|
@@ -955,7 +978,7 @@ async function runLoginModal(opts) {
|
|
|
955
978
|
});
|
|
956
979
|
return null; // unreachable
|
|
957
980
|
}
|
|
958
|
-
if (
|
|
981
|
+
if (routeChoice === 'qr') {
|
|
959
982
|
const result = await Promise.race([runRedirectFlow(refs, resolved), aborted]);
|
|
960
983
|
if (userAborted)
|
|
961
984
|
return null;
|
|
@@ -974,7 +997,7 @@ async function runLoginModal(opts) {
|
|
|
974
997
|
}
|
|
975
998
|
return session;
|
|
976
999
|
}
|
|
977
|
-
if (
|
|
1000
|
+
if (routeChoice === 'bunker') {
|
|
978
1001
|
const signer = await Promise.race([runBunkerFlow(refs, resolved), aborted]);
|
|
979
1002
|
if (userAborted)
|
|
980
1003
|
return null;
|
|
@@ -1000,7 +1023,7 @@ async function runLoginModal(opts) {
|
|
|
1000
1023
|
authEvent,
|
|
1001
1024
|
};
|
|
1002
1025
|
}
|
|
1003
|
-
if (
|
|
1026
|
+
if (routeChoice === 'nostrconnect') {
|
|
1004
1027
|
const signer = await Promise.race([runNostrConnectFlow(refs, resolved), aborted]);
|
|
1005
1028
|
if (userAborted)
|
|
1006
1029
|
return null;
|
|
@@ -1029,7 +1052,7 @@ async function runLoginModal(opts) {
|
|
|
1029
1052
|
authEvent,
|
|
1030
1053
|
};
|
|
1031
1054
|
}
|
|
1032
|
-
if (
|
|
1055
|
+
if (routeChoice === 'nsec') {
|
|
1033
1056
|
const signer = await Promise.race([runNsecFlow(refs, resolved), aborted]);
|
|
1034
1057
|
if (userAborted)
|
|
1035
1058
|
return null;
|
package/dist/signers.d.ts
CHANGED
|
@@ -85,11 +85,23 @@ export declare function buildNostrConnectUri(input: {
|
|
|
85
85
|
appUrl?: string;
|
|
86
86
|
}): string;
|
|
87
87
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
88
|
+
* Convert an app-generated `nostrconnect://` pairing URI into the equivalent
|
|
89
|
+
* signer-published `bunker://` reconnect URI once the signer pubkey is known.
|
|
90
|
+
*
|
|
91
|
+
* `nostrconnect://` is a one-time app-to-signer invitation; it only contains
|
|
92
|
+
* the client pubkey. After the signer responds, future restores should use
|
|
93
|
+
* `bunker://signerPubkey?...` with the same relays and secret.
|
|
94
|
+
*/
|
|
95
|
+
export declare function buildBunkerUriFromNostrConnectUri(nostrConnectUri: string, signerPubkeyHex: string): string;
|
|
96
|
+
export declare function isBunkerUri(value: string): boolean;
|
|
97
|
+
export declare function isNostrConnectUri(value: string): boolean;
|
|
98
|
+
export declare function isSupportedPairingUri(value: string): boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Connect a bunker session from a `bunker://` URI or NIP-05 identifier. Pass
|
|
101
|
+
* `clientSecretKey` to bind a stable client pubkey the signer can auto-approve
|
|
102
|
+
* (see `loadOrCreatePersistentClientSk`); when omitted a fresh ephemeral key is
|
|
103
|
+
* generated, which a per-pubkey-approving bunker will treat as a new,
|
|
104
|
+
* unapproved client.
|
|
93
105
|
*/
|
|
94
106
|
export declare function createBunkerSigner(input: {
|
|
95
107
|
uri: string;
|
package/dist/signers.js
CHANGED
|
@@ -118,7 +118,8 @@ export async function createBunkerSignerFromNostrConnect(input) {
|
|
|
118
118
|
await bunker.close().catch(() => { });
|
|
119
119
|
throw new Error('invalid-pubkey-from-bunker');
|
|
120
120
|
}
|
|
121
|
-
|
|
121
|
+
const normalizedBunkerUri = buildBunkerUriFromNostrConnectUri(uri, pubkey);
|
|
122
|
+
return new BunkerSignerImpl(pubkey.toLowerCase(), bunker, normalizedBunkerUri, clientSecretKey);
|
|
122
123
|
}
|
|
123
124
|
/**
|
|
124
125
|
* Build a NIP-46 `nostrconnect://` URI for the app-initiated flow. The
|
|
@@ -149,6 +150,50 @@ export function buildNostrConnectUri(input) {
|
|
|
149
150
|
params.set('url', input.appUrl);
|
|
150
151
|
return `nostrconnect://${clientPubkeyHex}?${params.toString()}`;
|
|
151
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* Convert an app-generated `nostrconnect://` pairing URI into the equivalent
|
|
155
|
+
* signer-published `bunker://` reconnect URI once the signer pubkey is known.
|
|
156
|
+
*
|
|
157
|
+
* `nostrconnect://` is a one-time app-to-signer invitation; it only contains
|
|
158
|
+
* the client pubkey. After the signer responds, future restores should use
|
|
159
|
+
* `bunker://signerPubkey?...` with the same relays and secret.
|
|
160
|
+
*/
|
|
161
|
+
export function buildBunkerUriFromNostrConnectUri(nostrConnectUri, signerPubkeyHex) {
|
|
162
|
+
if (!/^[0-9a-f]{64}$/i.test(signerPubkeyHex))
|
|
163
|
+
throw new Error('invalid-signer-pubkey');
|
|
164
|
+
let parsed;
|
|
165
|
+
try {
|
|
166
|
+
parsed = new URL(nostrConnectUri);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
throw new Error('invalid-nostrconnect-uri');
|
|
170
|
+
}
|
|
171
|
+
if (parsed.protocol !== 'nostrconnect:')
|
|
172
|
+
throw new Error('invalid-nostrconnect-uri');
|
|
173
|
+
const relays = parsed.searchParams.getAll('relay').map(relay => relay.trim()).filter(Boolean);
|
|
174
|
+
if (relays.length === 0)
|
|
175
|
+
throw new Error('relay-url-required');
|
|
176
|
+
for (const relayUrl of relays) {
|
|
177
|
+
if (!/^wss?:\/\//.test(relayUrl))
|
|
178
|
+
throw new Error('invalid-relay-url');
|
|
179
|
+
}
|
|
180
|
+
const secret = parsed.searchParams.get('secret');
|
|
181
|
+
const params = new URLSearchParams();
|
|
182
|
+
for (const relayUrl of relays)
|
|
183
|
+
params.append('relay', relayUrl);
|
|
184
|
+
if (secret)
|
|
185
|
+
params.set('secret', secret);
|
|
186
|
+
return `bunker://${signerPubkeyHex.toLowerCase()}?${params.toString()}`;
|
|
187
|
+
}
|
|
188
|
+
export function isBunkerUri(value) {
|
|
189
|
+
return value.trim().toLowerCase().startsWith('bunker://');
|
|
190
|
+
}
|
|
191
|
+
export function isNostrConnectUri(value) {
|
|
192
|
+
return value.trim().toLowerCase().startsWith('nostrconnect://');
|
|
193
|
+
}
|
|
194
|
+
export function isSupportedPairingUri(value) {
|
|
195
|
+
return isBunkerUri(value) || isNostrConnectUri(value);
|
|
196
|
+
}
|
|
152
197
|
/**
|
|
153
198
|
* Race a bunker handshake against a deadline. nostr-tools' `BunkerSigner`
|
|
154
199
|
* `sendRequest` has no per-request timeout — it publishes the request and only
|
|
@@ -177,11 +222,11 @@ async function raceBunkerHandshake(p, ms, bunker) {
|
|
|
177
222
|
}
|
|
178
223
|
}
|
|
179
224
|
/**
|
|
180
|
-
* Connect a bunker session from a `bunker://` or
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
225
|
+
* Connect a bunker session from a `bunker://` URI or NIP-05 identifier. Pass
|
|
226
|
+
* `clientSecretKey` to bind a stable client pubkey the signer can auto-approve
|
|
227
|
+
* (see `loadOrCreatePersistentClientSk`); when omitted a fresh ephemeral key is
|
|
228
|
+
* generated, which a per-pubkey-approving bunker will treat as a new,
|
|
229
|
+
* unapproved client.
|
|
185
230
|
*/
|
|
186
231
|
export async function createBunkerSigner(input) {
|
|
187
232
|
const trimmed = input.uri.trim();
|
package/dist/signet-login.d.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
export type { NostrEvent, EventTemplate, LoginMethod, LoginPickerMethod, SignerCapabilities, SignetSigner, SignetAuthEvent, SignetSession, LoginOptions, RestoreOptions, SignetStorage, } from './types.js';
|
|
18
18
|
import type { SignetSigner, LoginOptions, RestoreOptions, SignetSession, SignetAuthEvent, SignetStorage } from './types.js';
|
|
19
|
-
import { hasNip07, createNip07Signer, createBunkerSigner, createBunkerSignerFromNostrConnect, buildNostrConnectUri, createLocalSignerFromNsec, generateSecretKey, Nip07Signer, BunkerSignerImpl, LocalSigner } from './signers.js';
|
|
19
|
+
import { hasNip07, createNip07Signer, createBunkerSigner, createBunkerSignerFromNostrConnect, buildNostrConnectUri, buildBunkerUriFromNostrConnectUri, isBunkerUri, isNostrConnectUri, isSupportedPairingUri, createLocalSignerFromNsec, generateSecretKey, Nip07Signer, BunkerSignerImpl, LocalSigner } from './signers.js';
|
|
20
20
|
import { type ConsumeAmberResult } from './amber.js';
|
|
21
21
|
import { handleCallback as handlePopupCallback } from './callback.js';
|
|
22
22
|
import type { ConsumeCallbackResult } from './redirect.js';
|
|
@@ -24,7 +24,7 @@ export type { CallbackResult } from './callback.js';
|
|
|
24
24
|
export type { ConsumeCallbackResult } from './redirect.js';
|
|
25
25
|
export type { ConsumeAmberResult } from './amber.js';
|
|
26
26
|
export { isAndroid } from './amber.js';
|
|
27
|
-
export { hasNip07, createNip07Signer, createBunkerSigner, createBunkerSignerFromNostrConnect, buildNostrConnectUri, createLocalSignerFromNsec, generateSecretKey, Nip07Signer, BunkerSignerImpl, LocalSigner, };
|
|
27
|
+
export { hasNip07, createNip07Signer, createBunkerSigner, createBunkerSignerFromNostrConnect, buildNostrConnectUri, buildBunkerUriFromNostrConnectUri, isBunkerUri, isNostrConnectUri, isSupportedPairingUri, createLocalSignerFromNsec, generateSecretKey, Nip07Signer, BunkerSignerImpl, LocalSigner, };
|
|
28
28
|
export interface HandleRedirectCallbackOptions {
|
|
29
29
|
/**
|
|
30
30
|
* Await the returned `bunker://` handoff before resolving the callback.
|