@bzzsocial/ndk 3.0.3-bzz.7 → 3.0.3-bzz.8
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/index.d.mts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +22 -4
- package/dist/index.mjs +22 -4
- package/dist/test/index.d.mts +17 -7
- package/dist/test/index.d.ts +17 -7
- package/dist/test/index.js +22 -4
- package/dist/test/index.mjs +22 -4
- package/package.json +1 -1
- package/src/relay/auth-on-demand.test.ts +27 -0
- package/src/relay/connectivity.ts +17 -0
- package/src/relay/index.ts +10 -0
package/dist/index.d.mts
CHANGED
|
@@ -879,6 +879,8 @@ declare class NDKRelayConnectivity {
|
|
|
879
879
|
baseEoseTimeout: number;
|
|
880
880
|
/** The latest NIP-42 challenge on the current connection. */
|
|
881
881
|
authChallenge?: string;
|
|
882
|
+
/** The pubkey this connection is signed in as (NIP-42), until the connection closes. */
|
|
883
|
+
authedAs?: string;
|
|
882
884
|
private authInFlight?;
|
|
883
885
|
/** How long to wait for the relay's OK on an AUTH event, and for a signer to sign it. */
|
|
884
886
|
authTimeoutMs: number;
|
|
@@ -985,6 +987,7 @@ declare class NDKRelayConnectivity {
|
|
|
985
987
|
*/
|
|
986
988
|
authenticate(reason?: NDKAuthReason): Promise<boolean>;
|
|
987
989
|
private runAuth;
|
|
990
|
+
private attemptAuth;
|
|
988
991
|
private signAuthEvent;
|
|
989
992
|
private withAuthTimeout;
|
|
990
993
|
/**
|
|
@@ -1316,6 +1319,7 @@ interface NDKRelayConnectionStats {
|
|
|
1316
1319
|
* @emits NDKRelay#eose when the relay has reached the end of stored events
|
|
1317
1320
|
* @emits NDKRelay#auth when the relay requires authentication
|
|
1318
1321
|
* @emits NDKRelay#authed when the relay has authenticated
|
|
1322
|
+
* @emits NDKRelay#auth:settled when an AUTH attempt ends, whichever way (true: signed in)
|
|
1319
1323
|
* @emits NDKRelay#delayed-connect when the relay will wait before reconnecting
|
|
1320
1324
|
*/
|
|
1321
1325
|
declare class NDKRelay extends EventEmitter<{
|
|
@@ -1330,6 +1334,7 @@ declare class NDKRelay extends EventEmitter<{
|
|
|
1330
1334
|
auth: (challenge: string) => void;
|
|
1331
1335
|
authed: () => void;
|
|
1332
1336
|
"auth:failed": (error: Error) => void;
|
|
1337
|
+
"auth:settled": (authed: boolean) => void;
|
|
1333
1338
|
published: (event: NDKEvent) => void;
|
|
1334
1339
|
"publish:failed": (event: NDKEvent, error: Error) => void;
|
|
1335
1340
|
"delayed-connect": (delayInMs: number) => void;
|
|
@@ -1385,6 +1390,11 @@ declare class NDKRelay extends EventEmitter<{
|
|
|
1385
1390
|
* The NIP-42 challenge the relay sent on the current connection, if any.
|
|
1386
1391
|
*/
|
|
1387
1392
|
get authChallenge(): string | undefined;
|
|
1393
|
+
/**
|
|
1394
|
+
* The pubkey the current connection is signed in as (NIP-42), if it is. Cleared when the
|
|
1395
|
+
* connection closes: a new one signs in afresh.
|
|
1396
|
+
*/
|
|
1397
|
+
get authedAs(): string | undefined;
|
|
1388
1398
|
/**
|
|
1389
1399
|
* Answers the relay's NIP-42 challenge with this relay's auth policy (or the
|
|
1390
1400
|
* NDK default). Resolves true once the relay accepts, false otherwise.
|
package/dist/index.d.ts
CHANGED
|
@@ -879,6 +879,8 @@ declare class NDKRelayConnectivity {
|
|
|
879
879
|
baseEoseTimeout: number;
|
|
880
880
|
/** The latest NIP-42 challenge on the current connection. */
|
|
881
881
|
authChallenge?: string;
|
|
882
|
+
/** The pubkey this connection is signed in as (NIP-42), until the connection closes. */
|
|
883
|
+
authedAs?: string;
|
|
882
884
|
private authInFlight?;
|
|
883
885
|
/** How long to wait for the relay's OK on an AUTH event, and for a signer to sign it. */
|
|
884
886
|
authTimeoutMs: number;
|
|
@@ -985,6 +987,7 @@ declare class NDKRelayConnectivity {
|
|
|
985
987
|
*/
|
|
986
988
|
authenticate(reason?: NDKAuthReason): Promise<boolean>;
|
|
987
989
|
private runAuth;
|
|
990
|
+
private attemptAuth;
|
|
988
991
|
private signAuthEvent;
|
|
989
992
|
private withAuthTimeout;
|
|
990
993
|
/**
|
|
@@ -1316,6 +1319,7 @@ interface NDKRelayConnectionStats {
|
|
|
1316
1319
|
* @emits NDKRelay#eose when the relay has reached the end of stored events
|
|
1317
1320
|
* @emits NDKRelay#auth when the relay requires authentication
|
|
1318
1321
|
* @emits NDKRelay#authed when the relay has authenticated
|
|
1322
|
+
* @emits NDKRelay#auth:settled when an AUTH attempt ends, whichever way (true: signed in)
|
|
1319
1323
|
* @emits NDKRelay#delayed-connect when the relay will wait before reconnecting
|
|
1320
1324
|
*/
|
|
1321
1325
|
declare class NDKRelay extends EventEmitter<{
|
|
@@ -1330,6 +1334,7 @@ declare class NDKRelay extends EventEmitter<{
|
|
|
1330
1334
|
auth: (challenge: string) => void;
|
|
1331
1335
|
authed: () => void;
|
|
1332
1336
|
"auth:failed": (error: Error) => void;
|
|
1337
|
+
"auth:settled": (authed: boolean) => void;
|
|
1333
1338
|
published: (event: NDKEvent) => void;
|
|
1334
1339
|
"publish:failed": (event: NDKEvent, error: Error) => void;
|
|
1335
1340
|
"delayed-connect": (delayInMs: number) => void;
|
|
@@ -1385,6 +1390,11 @@ declare class NDKRelay extends EventEmitter<{
|
|
|
1385
1390
|
* The NIP-42 challenge the relay sent on the current connection, if any.
|
|
1386
1391
|
*/
|
|
1387
1392
|
get authChallenge(): string | undefined;
|
|
1393
|
+
/**
|
|
1394
|
+
* The pubkey the current connection is signed in as (NIP-42), if it is. Cleared when the
|
|
1395
|
+
* connection closes: a new one signs in afresh.
|
|
1396
|
+
*/
|
|
1397
|
+
get authedAs(): string | undefined;
|
|
1388
1398
|
/**
|
|
1389
1399
|
* Answers the relay's NIP-42 challenge with this relay's auth policy (or the
|
|
1390
1400
|
* NDK default). Resolves true once the relay accepts, false otherwise.
|
package/dist/index.js
CHANGED
|
@@ -831,6 +831,7 @@ var NDKRelayKeepalive = class {
|
|
|
831
831
|
this.onSilenceDetected = onSilenceDetected;
|
|
832
832
|
this.timeout = timeout;
|
|
833
833
|
}
|
|
834
|
+
onSilenceDetected;
|
|
834
835
|
lastActivity = Date.now();
|
|
835
836
|
timer;
|
|
836
837
|
timeout;
|
|
@@ -914,6 +915,8 @@ var NDKRelayConnectivity = class {
|
|
|
914
915
|
baseEoseTimeout = 4400;
|
|
915
916
|
/** The latest NIP-42 challenge on the current connection. */
|
|
916
917
|
authChallenge;
|
|
918
|
+
/** The pubkey this connection is signed in as (NIP-42), until the connection closes. */
|
|
919
|
+
authedAs;
|
|
917
920
|
authInFlight;
|
|
918
921
|
/** How long to wait for the relay's OK on an AUTH event, and for a signer to sign it. */
|
|
919
922
|
authTimeoutMs = 1e4;
|
|
@@ -1138,6 +1141,7 @@ var NDKRelayConnectivity = class {
|
|
|
1138
1141
|
this.updateConnectionStats.connected();
|
|
1139
1142
|
this._status = 5 /* CONNECTED */;
|
|
1140
1143
|
this.authChallenge = void 0;
|
|
1144
|
+
this.authedAs = void 0;
|
|
1141
1145
|
this.authWanted = void 0;
|
|
1142
1146
|
if (!this.wsStateMonitor) this.setupMonitoring();
|
|
1143
1147
|
this.keepalive?.start();
|
|
@@ -1166,6 +1170,7 @@ var NDKRelayConnectivity = class {
|
|
|
1166
1170
|
}
|
|
1167
1171
|
this._status = 1 /* DISCONNECTED */;
|
|
1168
1172
|
this.authChallenge = void 0;
|
|
1173
|
+
this.authedAs = void 0;
|
|
1169
1174
|
this.authWanted = void 0;
|
|
1170
1175
|
this.ndkRelay.emit("disconnect");
|
|
1171
1176
|
}
|
|
@@ -1333,6 +1338,11 @@ var NDKRelayConnectivity = class {
|
|
|
1333
1338
|
return attempt;
|
|
1334
1339
|
}
|
|
1335
1340
|
async runAuth(authPolicy, challenge, reason) {
|
|
1341
|
+
const authed = await this.attemptAuth(authPolicy, challenge, reason);
|
|
1342
|
+
this.ndkRelay.emit("auth:settled", authed);
|
|
1343
|
+
return authed;
|
|
1344
|
+
}
|
|
1345
|
+
async attemptAuth(authPolicy, challenge, reason) {
|
|
1336
1346
|
this._status = 7 /* AUTHENTICATING */;
|
|
1337
1347
|
try {
|
|
1338
1348
|
let res = await authPolicy(this.ndkRelay, challenge, reason);
|
|
@@ -1346,6 +1356,7 @@ var NDKRelayConnectivity = class {
|
|
|
1346
1356
|
await this.withAuthTimeout(this.auth(res));
|
|
1347
1357
|
if (this.authChallenge !== challenge || !this.connected) return false;
|
|
1348
1358
|
this._status = 8 /* AUTHENTICATED */;
|
|
1359
|
+
this.authedAs = res.pubkey;
|
|
1349
1360
|
this.debug("Authentication successful");
|
|
1350
1361
|
this.ndkRelay.emit("authed");
|
|
1351
1362
|
this.retryPendingAuthPublishes();
|
|
@@ -2572,6 +2583,13 @@ var NDKRelay = class _NDKRelay extends import_tseep.EventEmitter {
|
|
|
2572
2583
|
get authChallenge() {
|
|
2573
2584
|
return this.connectivity.authChallenge;
|
|
2574
2585
|
}
|
|
2586
|
+
/**
|
|
2587
|
+
* The pubkey the current connection is signed in as (NIP-42), if it is. Cleared when the
|
|
2588
|
+
* connection closes: a new one signs in afresh.
|
|
2589
|
+
*/
|
|
2590
|
+
get authedAs() {
|
|
2591
|
+
return this.connectivity.authedAs;
|
|
2592
|
+
}
|
|
2575
2593
|
/**
|
|
2576
2594
|
* Answers the relay's NIP-42 challenge with this relay's auth policy (or the
|
|
2577
2595
|
* NDK default). Resolves true once the relay accepts, false otherwise.
|
|
@@ -3728,13 +3746,13 @@ function signatureVerificationInit(w) {
|
|
|
3728
3746
|
msg.data,
|
|
3729
3747
|
"\n\n\u{1F50D} This likely means:",
|
|
3730
3748
|
"\n 1. You have a STALE worker.js file that needs updating",
|
|
3731
|
-
"\n 2. Version mismatch between @
|
|
3749
|
+
"\n 2. Version mismatch between @bzzsocial/ndk and deployed worker",
|
|
3732
3750
|
"\n 3. Wrong worker is being used for signature verification",
|
|
3733
3751
|
"\n\n\u2705 Solution: Update your worker files:",
|
|
3734
|
-
"\n cp node_modules/@
|
|
3752
|
+
"\n cp node_modules/@bzzsocial/ndk/dist/workers/sig-verification.js public/",
|
|
3735
3753
|
"\n cp node_modules/@nostr-dev-kit/cache-sqlite-wasm/dist/worker.js public/",
|
|
3736
3754
|
"\n\n\u{1F4A1} Or use Vite/bundler imports instead of static files:",
|
|
3737
|
-
'\n import SigWorker from "@
|
|
3755
|
+
'\n import SigWorker from "@bzzsocial/ndk/workers/sig-verification?worker"'
|
|
3738
3756
|
);
|
|
3739
3757
|
return;
|
|
3740
3758
|
}
|
|
@@ -9444,7 +9462,7 @@ No events can match this time range!`,
|
|
|
9444
9462
|
guards.error(
|
|
9445
9463
|
GuardrailCheckId.FILTER_BECH32_IN_ARRAY,
|
|
9446
9464
|
`Filter[${filterIndex}].ids[${idx}] contains bech32: "${id}". IDs must be hex, not bech32.`,
|
|
9447
|
-
`Use filterFromId() to decode bech32 first: import { filterFromId } from "@
|
|
9465
|
+
`Use filterFromId() to decode bech32 first: import { filterFromId } from "@bzzsocial/ndk"`,
|
|
9448
9466
|
false
|
|
9449
9467
|
// Fatal error - cannot be disabled
|
|
9450
9468
|
);
|
package/dist/index.mjs
CHANGED
|
@@ -652,6 +652,7 @@ var NDKRelayKeepalive = class {
|
|
|
652
652
|
this.onSilenceDetected = onSilenceDetected;
|
|
653
653
|
this.timeout = timeout;
|
|
654
654
|
}
|
|
655
|
+
onSilenceDetected;
|
|
655
656
|
lastActivity = Date.now();
|
|
656
657
|
timer;
|
|
657
658
|
timeout;
|
|
@@ -735,6 +736,8 @@ var NDKRelayConnectivity = class {
|
|
|
735
736
|
baseEoseTimeout = 4400;
|
|
736
737
|
/** The latest NIP-42 challenge on the current connection. */
|
|
737
738
|
authChallenge;
|
|
739
|
+
/** The pubkey this connection is signed in as (NIP-42), until the connection closes. */
|
|
740
|
+
authedAs;
|
|
738
741
|
authInFlight;
|
|
739
742
|
/** How long to wait for the relay's OK on an AUTH event, and for a signer to sign it. */
|
|
740
743
|
authTimeoutMs = 1e4;
|
|
@@ -959,6 +962,7 @@ var NDKRelayConnectivity = class {
|
|
|
959
962
|
this.updateConnectionStats.connected();
|
|
960
963
|
this._status = 5 /* CONNECTED */;
|
|
961
964
|
this.authChallenge = void 0;
|
|
965
|
+
this.authedAs = void 0;
|
|
962
966
|
this.authWanted = void 0;
|
|
963
967
|
if (!this.wsStateMonitor) this.setupMonitoring();
|
|
964
968
|
this.keepalive?.start();
|
|
@@ -987,6 +991,7 @@ var NDKRelayConnectivity = class {
|
|
|
987
991
|
}
|
|
988
992
|
this._status = 1 /* DISCONNECTED */;
|
|
989
993
|
this.authChallenge = void 0;
|
|
994
|
+
this.authedAs = void 0;
|
|
990
995
|
this.authWanted = void 0;
|
|
991
996
|
this.ndkRelay.emit("disconnect");
|
|
992
997
|
}
|
|
@@ -1154,6 +1159,11 @@ var NDKRelayConnectivity = class {
|
|
|
1154
1159
|
return attempt;
|
|
1155
1160
|
}
|
|
1156
1161
|
async runAuth(authPolicy, challenge, reason) {
|
|
1162
|
+
const authed = await this.attemptAuth(authPolicy, challenge, reason);
|
|
1163
|
+
this.ndkRelay.emit("auth:settled", authed);
|
|
1164
|
+
return authed;
|
|
1165
|
+
}
|
|
1166
|
+
async attemptAuth(authPolicy, challenge, reason) {
|
|
1157
1167
|
this._status = 7 /* AUTHENTICATING */;
|
|
1158
1168
|
try {
|
|
1159
1169
|
let res = await authPolicy(this.ndkRelay, challenge, reason);
|
|
@@ -1167,6 +1177,7 @@ var NDKRelayConnectivity = class {
|
|
|
1167
1177
|
await this.withAuthTimeout(this.auth(res));
|
|
1168
1178
|
if (this.authChallenge !== challenge || !this.connected) return false;
|
|
1169
1179
|
this._status = 8 /* AUTHENTICATED */;
|
|
1180
|
+
this.authedAs = res.pubkey;
|
|
1170
1181
|
this.debug("Authentication successful");
|
|
1171
1182
|
this.ndkRelay.emit("authed");
|
|
1172
1183
|
this.retryPendingAuthPublishes();
|
|
@@ -2393,6 +2404,13 @@ var NDKRelay = class _NDKRelay extends EventEmitter {
|
|
|
2393
2404
|
get authChallenge() {
|
|
2394
2405
|
return this.connectivity.authChallenge;
|
|
2395
2406
|
}
|
|
2407
|
+
/**
|
|
2408
|
+
* The pubkey the current connection is signed in as (NIP-42), if it is. Cleared when the
|
|
2409
|
+
* connection closes: a new one signs in afresh.
|
|
2410
|
+
*/
|
|
2411
|
+
get authedAs() {
|
|
2412
|
+
return this.connectivity.authedAs;
|
|
2413
|
+
}
|
|
2396
2414
|
/**
|
|
2397
2415
|
* Answers the relay's NIP-42 challenge with this relay's auth policy (or the
|
|
2398
2416
|
* NDK default). Resolves true once the relay accepts, false otherwise.
|
|
@@ -3549,13 +3567,13 @@ function signatureVerificationInit(w) {
|
|
|
3549
3567
|
msg.data,
|
|
3550
3568
|
"\n\n\u{1F50D} This likely means:",
|
|
3551
3569
|
"\n 1. You have a STALE worker.js file that needs updating",
|
|
3552
|
-
"\n 2. Version mismatch between @
|
|
3570
|
+
"\n 2. Version mismatch between @bzzsocial/ndk and deployed worker",
|
|
3553
3571
|
"\n 3. Wrong worker is being used for signature verification",
|
|
3554
3572
|
"\n\n\u2705 Solution: Update your worker files:",
|
|
3555
|
-
"\n cp node_modules/@
|
|
3573
|
+
"\n cp node_modules/@bzzsocial/ndk/dist/workers/sig-verification.js public/",
|
|
3556
3574
|
"\n cp node_modules/@nostr-dev-kit/cache-sqlite-wasm/dist/worker.js public/",
|
|
3557
3575
|
"\n\n\u{1F4A1} Or use Vite/bundler imports instead of static files:",
|
|
3558
|
-
'\n import SigWorker from "@
|
|
3576
|
+
'\n import SigWorker from "@bzzsocial/ndk/workers/sig-verification?worker"'
|
|
3559
3577
|
);
|
|
3560
3578
|
return;
|
|
3561
3579
|
}
|
|
@@ -9265,7 +9283,7 @@ No events can match this time range!`,
|
|
|
9265
9283
|
guards.error(
|
|
9266
9284
|
GuardrailCheckId.FILTER_BECH32_IN_ARRAY,
|
|
9267
9285
|
`Filter[${filterIndex}].ids[${idx}] contains bech32: "${id}". IDs must be hex, not bech32.`,
|
|
9268
|
-
`Use filterFromId() to decode bech32 first: import { filterFromId } from "@
|
|
9286
|
+
`Use filterFromId() to decode bech32 first: import { filterFromId } from "@bzzsocial/ndk"`,
|
|
9269
9287
|
false
|
|
9270
9288
|
// Fatal error - cannot be disabled
|
|
9271
9289
|
);
|
package/dist/test/index.d.mts
CHANGED
|
@@ -778,6 +778,8 @@ declare class NDKRelayConnectivity {
|
|
|
778
778
|
baseEoseTimeout: number;
|
|
779
779
|
/** The latest NIP-42 challenge on the current connection. */
|
|
780
780
|
authChallenge?: string;
|
|
781
|
+
/** The pubkey this connection is signed in as (NIP-42), until the connection closes. */
|
|
782
|
+
authedAs?: string;
|
|
781
783
|
private authInFlight?;
|
|
782
784
|
/** How long to wait for the relay's OK on an AUTH event, and for a signer to sign it. */
|
|
783
785
|
authTimeoutMs: number;
|
|
@@ -884,6 +886,7 @@ declare class NDKRelayConnectivity {
|
|
|
884
886
|
*/
|
|
885
887
|
authenticate(reason?: NDKAuthReason): Promise<boolean>;
|
|
886
888
|
private runAuth;
|
|
889
|
+
private attemptAuth;
|
|
887
890
|
private signAuthEvent;
|
|
888
891
|
private withAuthTimeout;
|
|
889
892
|
/**
|
|
@@ -1163,6 +1166,7 @@ interface NDKRelayConnectionStats {
|
|
|
1163
1166
|
* @emits NDKRelay#eose when the relay has reached the end of stored events
|
|
1164
1167
|
* @emits NDKRelay#auth when the relay requires authentication
|
|
1165
1168
|
* @emits NDKRelay#authed when the relay has authenticated
|
|
1169
|
+
* @emits NDKRelay#auth:settled when an AUTH attempt ends, whichever way (true: signed in)
|
|
1166
1170
|
* @emits NDKRelay#delayed-connect when the relay will wait before reconnecting
|
|
1167
1171
|
*/
|
|
1168
1172
|
declare class NDKRelay extends EventEmitter<{
|
|
@@ -1177,6 +1181,7 @@ declare class NDKRelay extends EventEmitter<{
|
|
|
1177
1181
|
auth: (challenge: string) => void;
|
|
1178
1182
|
authed: () => void;
|
|
1179
1183
|
"auth:failed": (error: Error) => void;
|
|
1184
|
+
"auth:settled": (authed: boolean) => void;
|
|
1180
1185
|
published: (event: NDKEvent) => void;
|
|
1181
1186
|
"publish:failed": (event: NDKEvent, error: Error) => void;
|
|
1182
1187
|
"delayed-connect": (delayInMs: number) => void;
|
|
@@ -1232,6 +1237,11 @@ declare class NDKRelay extends EventEmitter<{
|
|
|
1232
1237
|
* The NIP-42 challenge the relay sent on the current connection, if any.
|
|
1233
1238
|
*/
|
|
1234
1239
|
get authChallenge(): string | undefined;
|
|
1240
|
+
/**
|
|
1241
|
+
* The pubkey the current connection is signed in as (NIP-42), if it is. Cleared when the
|
|
1242
|
+
* connection closes: a new one signs in afresh.
|
|
1243
|
+
*/
|
|
1244
|
+
get authedAs(): string | undefined;
|
|
1235
1245
|
/**
|
|
1236
1246
|
* Answers the relay's NIP-42 challenge with this relay's auth policy (or the
|
|
1237
1247
|
* NDK default). Resolves true once the relay accepts, false otherwise.
|
|
@@ -4244,7 +4254,7 @@ declare class TestFixture {
|
|
|
4244
4254
|
* @example
|
|
4245
4255
|
* ```typescript
|
|
4246
4256
|
* import { vi } from 'vitest';
|
|
4247
|
-
* import { TimeController } from '@
|
|
4257
|
+
* import { TimeController } from '@bzzsocial/ndk/test';
|
|
4248
4258
|
*
|
|
4249
4259
|
* beforeEach(() => {
|
|
4250
4260
|
* vi.useFakeTimers();
|
|
@@ -4301,7 +4311,7 @@ declare class TimeController {
|
|
|
4301
4311
|
* @example
|
|
4302
4312
|
* ```typescript
|
|
4303
4313
|
* import { vi } from 'vitest';
|
|
4304
|
-
* import { withTimeControl } from '@
|
|
4314
|
+
* import { withTimeControl } from '@bzzsocial/ndk/test';
|
|
4305
4315
|
*
|
|
4306
4316
|
* const timeController = withTimeControl(vi);
|
|
4307
4317
|
*
|
|
@@ -4325,7 +4335,7 @@ declare function withTimeControl(viObject: any): (fn: (timeController: typeof Ti
|
|
|
4325
4335
|
*
|
|
4326
4336
|
* @example
|
|
4327
4337
|
* ```typescript
|
|
4328
|
-
* import { EventGenerator, UserGenerator } from '@
|
|
4338
|
+
* import { EventGenerator, UserGenerator } from '@bzzsocial/ndk/test';
|
|
4329
4339
|
*
|
|
4330
4340
|
* // Initialize once in your test setup
|
|
4331
4341
|
* EventGenerator.setNDK(ndk);
|
|
@@ -4375,7 +4385,7 @@ type Proof = {
|
|
|
4375
4385
|
*
|
|
4376
4386
|
* @example
|
|
4377
4387
|
* ```typescript
|
|
4378
|
-
* import { mockNutzap, UserGenerator } from '@
|
|
4388
|
+
* import { mockNutzap, UserGenerator } from '@bzzsocial/ndk/test';
|
|
4379
4389
|
*
|
|
4380
4390
|
* const alice = await UserGenerator.getUser('alice', ndk);
|
|
4381
4391
|
* const bob = await UserGenerator.getUser('bob', ndk);
|
|
@@ -4416,7 +4426,7 @@ declare function mockNutzap(mint: string, amount: number, ndk: any, { senderPk,
|
|
|
4416
4426
|
*
|
|
4417
4427
|
* @example
|
|
4418
4428
|
* ```typescript
|
|
4419
|
-
* import { mockProof } from '@
|
|
4429
|
+
* import { mockProof } from '@bzzsocial/ndk/test';
|
|
4420
4430
|
*
|
|
4421
4431
|
* // Create a simple proof
|
|
4422
4432
|
* const proof = mockProof('https://mint.example.com', 100);
|
|
@@ -4451,7 +4461,7 @@ interface RelayMockOptions {
|
|
|
4451
4461
|
*
|
|
4452
4462
|
* @example
|
|
4453
4463
|
* ```typescript
|
|
4454
|
-
* import { RelayMock } from '@
|
|
4464
|
+
* import { RelayMock } from '@bzzsocial/ndk/test';
|
|
4455
4465
|
*
|
|
4456
4466
|
* // Create a mock relay
|
|
4457
4467
|
* const relay = new RelayMock('wss://relay.example.com', {
|
|
@@ -4528,7 +4538,7 @@ declare class RelayMock extends EventEmitter$1 {
|
|
|
4528
4538
|
*
|
|
4529
4539
|
* @example
|
|
4530
4540
|
* ```typescript
|
|
4531
|
-
* import { RelayPoolMock, EventGenerator, UserGenerator } from '@
|
|
4541
|
+
* import { RelayPoolMock, EventGenerator, UserGenerator } from '@bzzsocial/ndk/test';
|
|
4532
4542
|
*
|
|
4533
4543
|
* const pool = new RelayPoolMock();
|
|
4534
4544
|
* const ndk = new NDK({ explicitRelayUrls: [] });
|
package/dist/test/index.d.ts
CHANGED
|
@@ -778,6 +778,8 @@ declare class NDKRelayConnectivity {
|
|
|
778
778
|
baseEoseTimeout: number;
|
|
779
779
|
/** The latest NIP-42 challenge on the current connection. */
|
|
780
780
|
authChallenge?: string;
|
|
781
|
+
/** The pubkey this connection is signed in as (NIP-42), until the connection closes. */
|
|
782
|
+
authedAs?: string;
|
|
781
783
|
private authInFlight?;
|
|
782
784
|
/** How long to wait for the relay's OK on an AUTH event, and for a signer to sign it. */
|
|
783
785
|
authTimeoutMs: number;
|
|
@@ -884,6 +886,7 @@ declare class NDKRelayConnectivity {
|
|
|
884
886
|
*/
|
|
885
887
|
authenticate(reason?: NDKAuthReason): Promise<boolean>;
|
|
886
888
|
private runAuth;
|
|
889
|
+
private attemptAuth;
|
|
887
890
|
private signAuthEvent;
|
|
888
891
|
private withAuthTimeout;
|
|
889
892
|
/**
|
|
@@ -1163,6 +1166,7 @@ interface NDKRelayConnectionStats {
|
|
|
1163
1166
|
* @emits NDKRelay#eose when the relay has reached the end of stored events
|
|
1164
1167
|
* @emits NDKRelay#auth when the relay requires authentication
|
|
1165
1168
|
* @emits NDKRelay#authed when the relay has authenticated
|
|
1169
|
+
* @emits NDKRelay#auth:settled when an AUTH attempt ends, whichever way (true: signed in)
|
|
1166
1170
|
* @emits NDKRelay#delayed-connect when the relay will wait before reconnecting
|
|
1167
1171
|
*/
|
|
1168
1172
|
declare class NDKRelay extends EventEmitter<{
|
|
@@ -1177,6 +1181,7 @@ declare class NDKRelay extends EventEmitter<{
|
|
|
1177
1181
|
auth: (challenge: string) => void;
|
|
1178
1182
|
authed: () => void;
|
|
1179
1183
|
"auth:failed": (error: Error) => void;
|
|
1184
|
+
"auth:settled": (authed: boolean) => void;
|
|
1180
1185
|
published: (event: NDKEvent) => void;
|
|
1181
1186
|
"publish:failed": (event: NDKEvent, error: Error) => void;
|
|
1182
1187
|
"delayed-connect": (delayInMs: number) => void;
|
|
@@ -1232,6 +1237,11 @@ declare class NDKRelay extends EventEmitter<{
|
|
|
1232
1237
|
* The NIP-42 challenge the relay sent on the current connection, if any.
|
|
1233
1238
|
*/
|
|
1234
1239
|
get authChallenge(): string | undefined;
|
|
1240
|
+
/**
|
|
1241
|
+
* The pubkey the current connection is signed in as (NIP-42), if it is. Cleared when the
|
|
1242
|
+
* connection closes: a new one signs in afresh.
|
|
1243
|
+
*/
|
|
1244
|
+
get authedAs(): string | undefined;
|
|
1235
1245
|
/**
|
|
1236
1246
|
* Answers the relay's NIP-42 challenge with this relay's auth policy (or the
|
|
1237
1247
|
* NDK default). Resolves true once the relay accepts, false otherwise.
|
|
@@ -4244,7 +4254,7 @@ declare class TestFixture {
|
|
|
4244
4254
|
* @example
|
|
4245
4255
|
* ```typescript
|
|
4246
4256
|
* import { vi } from 'vitest';
|
|
4247
|
-
* import { TimeController } from '@
|
|
4257
|
+
* import { TimeController } from '@bzzsocial/ndk/test';
|
|
4248
4258
|
*
|
|
4249
4259
|
* beforeEach(() => {
|
|
4250
4260
|
* vi.useFakeTimers();
|
|
@@ -4301,7 +4311,7 @@ declare class TimeController {
|
|
|
4301
4311
|
* @example
|
|
4302
4312
|
* ```typescript
|
|
4303
4313
|
* import { vi } from 'vitest';
|
|
4304
|
-
* import { withTimeControl } from '@
|
|
4314
|
+
* import { withTimeControl } from '@bzzsocial/ndk/test';
|
|
4305
4315
|
*
|
|
4306
4316
|
* const timeController = withTimeControl(vi);
|
|
4307
4317
|
*
|
|
@@ -4325,7 +4335,7 @@ declare function withTimeControl(viObject: any): (fn: (timeController: typeof Ti
|
|
|
4325
4335
|
*
|
|
4326
4336
|
* @example
|
|
4327
4337
|
* ```typescript
|
|
4328
|
-
* import { EventGenerator, UserGenerator } from '@
|
|
4338
|
+
* import { EventGenerator, UserGenerator } from '@bzzsocial/ndk/test';
|
|
4329
4339
|
*
|
|
4330
4340
|
* // Initialize once in your test setup
|
|
4331
4341
|
* EventGenerator.setNDK(ndk);
|
|
@@ -4375,7 +4385,7 @@ type Proof = {
|
|
|
4375
4385
|
*
|
|
4376
4386
|
* @example
|
|
4377
4387
|
* ```typescript
|
|
4378
|
-
* import { mockNutzap, UserGenerator } from '@
|
|
4388
|
+
* import { mockNutzap, UserGenerator } from '@bzzsocial/ndk/test';
|
|
4379
4389
|
*
|
|
4380
4390
|
* const alice = await UserGenerator.getUser('alice', ndk);
|
|
4381
4391
|
* const bob = await UserGenerator.getUser('bob', ndk);
|
|
@@ -4416,7 +4426,7 @@ declare function mockNutzap(mint: string, amount: number, ndk: any, { senderPk,
|
|
|
4416
4426
|
*
|
|
4417
4427
|
* @example
|
|
4418
4428
|
* ```typescript
|
|
4419
|
-
* import { mockProof } from '@
|
|
4429
|
+
* import { mockProof } from '@bzzsocial/ndk/test';
|
|
4420
4430
|
*
|
|
4421
4431
|
* // Create a simple proof
|
|
4422
4432
|
* const proof = mockProof('https://mint.example.com', 100);
|
|
@@ -4451,7 +4461,7 @@ interface RelayMockOptions {
|
|
|
4451
4461
|
*
|
|
4452
4462
|
* @example
|
|
4453
4463
|
* ```typescript
|
|
4454
|
-
* import { RelayMock } from '@
|
|
4464
|
+
* import { RelayMock } from '@bzzsocial/ndk/test';
|
|
4455
4465
|
*
|
|
4456
4466
|
* // Create a mock relay
|
|
4457
4467
|
* const relay = new RelayMock('wss://relay.example.com', {
|
|
@@ -4528,7 +4538,7 @@ declare class RelayMock extends EventEmitter$1 {
|
|
|
4528
4538
|
*
|
|
4529
4539
|
* @example
|
|
4530
4540
|
* ```typescript
|
|
4531
|
-
* import { RelayPoolMock, EventGenerator, UserGenerator } from '@
|
|
4541
|
+
* import { RelayPoolMock, EventGenerator, UserGenerator } from '@bzzsocial/ndk/test';
|
|
4532
4542
|
*
|
|
4533
4543
|
* const pool = new RelayPoolMock();
|
|
4534
4544
|
* const ndk = new NDK({ explicitRelayUrls: [] });
|
package/dist/test/index.js
CHANGED
|
@@ -1138,6 +1138,7 @@ var NDKRelayKeepalive = class {
|
|
|
1138
1138
|
this.onSilenceDetected = onSilenceDetected;
|
|
1139
1139
|
this.timeout = timeout;
|
|
1140
1140
|
}
|
|
1141
|
+
onSilenceDetected;
|
|
1141
1142
|
lastActivity = Date.now();
|
|
1142
1143
|
timer;
|
|
1143
1144
|
timeout;
|
|
@@ -1221,6 +1222,8 @@ var NDKRelayConnectivity = class {
|
|
|
1221
1222
|
baseEoseTimeout = 4400;
|
|
1222
1223
|
/** The latest NIP-42 challenge on the current connection. */
|
|
1223
1224
|
authChallenge;
|
|
1225
|
+
/** The pubkey this connection is signed in as (NIP-42), until the connection closes. */
|
|
1226
|
+
authedAs;
|
|
1224
1227
|
authInFlight;
|
|
1225
1228
|
/** How long to wait for the relay's OK on an AUTH event, and for a signer to sign it. */
|
|
1226
1229
|
authTimeoutMs = 1e4;
|
|
@@ -1445,6 +1448,7 @@ var NDKRelayConnectivity = class {
|
|
|
1445
1448
|
this.updateConnectionStats.connected();
|
|
1446
1449
|
this._status = 5 /* CONNECTED */;
|
|
1447
1450
|
this.authChallenge = void 0;
|
|
1451
|
+
this.authedAs = void 0;
|
|
1448
1452
|
this.authWanted = void 0;
|
|
1449
1453
|
if (!this.wsStateMonitor) this.setupMonitoring();
|
|
1450
1454
|
this.keepalive?.start();
|
|
@@ -1473,6 +1477,7 @@ var NDKRelayConnectivity = class {
|
|
|
1473
1477
|
}
|
|
1474
1478
|
this._status = 1 /* DISCONNECTED */;
|
|
1475
1479
|
this.authChallenge = void 0;
|
|
1480
|
+
this.authedAs = void 0;
|
|
1476
1481
|
this.authWanted = void 0;
|
|
1477
1482
|
this.ndkRelay.emit("disconnect");
|
|
1478
1483
|
}
|
|
@@ -1640,6 +1645,11 @@ var NDKRelayConnectivity = class {
|
|
|
1640
1645
|
return attempt;
|
|
1641
1646
|
}
|
|
1642
1647
|
async runAuth(authPolicy, challenge, reason) {
|
|
1648
|
+
const authed = await this.attemptAuth(authPolicy, challenge, reason);
|
|
1649
|
+
this.ndkRelay.emit("auth:settled", authed);
|
|
1650
|
+
return authed;
|
|
1651
|
+
}
|
|
1652
|
+
async attemptAuth(authPolicy, challenge, reason) {
|
|
1643
1653
|
this._status = 7 /* AUTHENTICATING */;
|
|
1644
1654
|
try {
|
|
1645
1655
|
let res = await authPolicy(this.ndkRelay, challenge, reason);
|
|
@@ -1653,6 +1663,7 @@ var NDKRelayConnectivity = class {
|
|
|
1653
1663
|
await this.withAuthTimeout(this.auth(res));
|
|
1654
1664
|
if (this.authChallenge !== challenge || !this.connected) return false;
|
|
1655
1665
|
this._status = 8 /* AUTHENTICATED */;
|
|
1666
|
+
this.authedAs = res.pubkey;
|
|
1656
1667
|
this.debug("Authentication successful");
|
|
1657
1668
|
this.ndkRelay.emit("authed");
|
|
1658
1669
|
this.retryPendingAuthPublishes();
|
|
@@ -2757,6 +2768,13 @@ var NDKRelay = class _NDKRelay extends import_tseep.EventEmitter {
|
|
|
2757
2768
|
get authChallenge() {
|
|
2758
2769
|
return this.connectivity.authChallenge;
|
|
2759
2770
|
}
|
|
2771
|
+
/**
|
|
2772
|
+
* The pubkey the current connection is signed in as (NIP-42), if it is. Cleared when the
|
|
2773
|
+
* connection closes: a new one signs in afresh.
|
|
2774
|
+
*/
|
|
2775
|
+
get authedAs() {
|
|
2776
|
+
return this.connectivity.authedAs;
|
|
2777
|
+
}
|
|
2760
2778
|
/**
|
|
2761
2779
|
* Answers the relay's NIP-42 challenge with this relay's auth policy (or the
|
|
2762
2780
|
* NDK default). Resolves true once the relay accepts, false otherwise.
|
|
@@ -3817,13 +3835,13 @@ function signatureVerificationInit(w) {
|
|
|
3817
3835
|
msg.data,
|
|
3818
3836
|
"\n\n\u{1F50D} This likely means:",
|
|
3819
3837
|
"\n 1. You have a STALE worker.js file that needs updating",
|
|
3820
|
-
"\n 2. Version mismatch between @
|
|
3838
|
+
"\n 2. Version mismatch between @bzzsocial/ndk and deployed worker",
|
|
3821
3839
|
"\n 3. Wrong worker is being used for signature verification",
|
|
3822
3840
|
"\n\n\u2705 Solution: Update your worker files:",
|
|
3823
|
-
"\n cp node_modules/@
|
|
3841
|
+
"\n cp node_modules/@bzzsocial/ndk/dist/workers/sig-verification.js public/",
|
|
3824
3842
|
"\n cp node_modules/@nostr-dev-kit/cache-sqlite-wasm/dist/worker.js public/",
|
|
3825
3843
|
"\n\n\u{1F4A1} Or use Vite/bundler imports instead of static files:",
|
|
3826
|
-
'\n import SigWorker from "@
|
|
3844
|
+
'\n import SigWorker from "@bzzsocial/ndk/workers/sig-verification?worker"'
|
|
3827
3845
|
);
|
|
3828
3846
|
return;
|
|
3829
3847
|
}
|
|
@@ -10812,7 +10830,7 @@ No events can match this time range!`,
|
|
|
10812
10830
|
guards.error(
|
|
10813
10831
|
GuardrailCheckId.FILTER_BECH32_IN_ARRAY,
|
|
10814
10832
|
`Filter[${filterIndex}].ids[${idx}] contains bech32: "${id}". IDs must be hex, not bech32.`,
|
|
10815
|
-
`Use filterFromId() to decode bech32 first: import { filterFromId } from "@
|
|
10833
|
+
`Use filterFromId() to decode bech32 first: import { filterFromId } from "@bzzsocial/ndk"`,
|
|
10816
10834
|
false
|
|
10817
10835
|
// Fatal error - cannot be disabled
|
|
10818
10836
|
);
|
package/dist/test/index.mjs
CHANGED
|
@@ -1105,6 +1105,7 @@ var NDKRelayKeepalive = class {
|
|
|
1105
1105
|
this.onSilenceDetected = onSilenceDetected;
|
|
1106
1106
|
this.timeout = timeout;
|
|
1107
1107
|
}
|
|
1108
|
+
onSilenceDetected;
|
|
1108
1109
|
lastActivity = Date.now();
|
|
1109
1110
|
timer;
|
|
1110
1111
|
timeout;
|
|
@@ -1188,6 +1189,8 @@ var NDKRelayConnectivity = class {
|
|
|
1188
1189
|
baseEoseTimeout = 4400;
|
|
1189
1190
|
/** The latest NIP-42 challenge on the current connection. */
|
|
1190
1191
|
authChallenge;
|
|
1192
|
+
/** The pubkey this connection is signed in as (NIP-42), until the connection closes. */
|
|
1193
|
+
authedAs;
|
|
1191
1194
|
authInFlight;
|
|
1192
1195
|
/** How long to wait for the relay's OK on an AUTH event, and for a signer to sign it. */
|
|
1193
1196
|
authTimeoutMs = 1e4;
|
|
@@ -1412,6 +1415,7 @@ var NDKRelayConnectivity = class {
|
|
|
1412
1415
|
this.updateConnectionStats.connected();
|
|
1413
1416
|
this._status = 5 /* CONNECTED */;
|
|
1414
1417
|
this.authChallenge = void 0;
|
|
1418
|
+
this.authedAs = void 0;
|
|
1415
1419
|
this.authWanted = void 0;
|
|
1416
1420
|
if (!this.wsStateMonitor) this.setupMonitoring();
|
|
1417
1421
|
this.keepalive?.start();
|
|
@@ -1440,6 +1444,7 @@ var NDKRelayConnectivity = class {
|
|
|
1440
1444
|
}
|
|
1441
1445
|
this._status = 1 /* DISCONNECTED */;
|
|
1442
1446
|
this.authChallenge = void 0;
|
|
1447
|
+
this.authedAs = void 0;
|
|
1443
1448
|
this.authWanted = void 0;
|
|
1444
1449
|
this.ndkRelay.emit("disconnect");
|
|
1445
1450
|
}
|
|
@@ -1607,6 +1612,11 @@ var NDKRelayConnectivity = class {
|
|
|
1607
1612
|
return attempt;
|
|
1608
1613
|
}
|
|
1609
1614
|
async runAuth(authPolicy, challenge, reason) {
|
|
1615
|
+
const authed = await this.attemptAuth(authPolicy, challenge, reason);
|
|
1616
|
+
this.ndkRelay.emit("auth:settled", authed);
|
|
1617
|
+
return authed;
|
|
1618
|
+
}
|
|
1619
|
+
async attemptAuth(authPolicy, challenge, reason) {
|
|
1610
1620
|
this._status = 7 /* AUTHENTICATING */;
|
|
1611
1621
|
try {
|
|
1612
1622
|
let res = await authPolicy(this.ndkRelay, challenge, reason);
|
|
@@ -1620,6 +1630,7 @@ var NDKRelayConnectivity = class {
|
|
|
1620
1630
|
await this.withAuthTimeout(this.auth(res));
|
|
1621
1631
|
if (this.authChallenge !== challenge || !this.connected) return false;
|
|
1622
1632
|
this._status = 8 /* AUTHENTICATED */;
|
|
1633
|
+
this.authedAs = res.pubkey;
|
|
1623
1634
|
this.debug("Authentication successful");
|
|
1624
1635
|
this.ndkRelay.emit("authed");
|
|
1625
1636
|
this.retryPendingAuthPublishes();
|
|
@@ -2724,6 +2735,13 @@ var NDKRelay = class _NDKRelay extends EventEmitter {
|
|
|
2724
2735
|
get authChallenge() {
|
|
2725
2736
|
return this.connectivity.authChallenge;
|
|
2726
2737
|
}
|
|
2738
|
+
/**
|
|
2739
|
+
* The pubkey the current connection is signed in as (NIP-42), if it is. Cleared when the
|
|
2740
|
+
* connection closes: a new one signs in afresh.
|
|
2741
|
+
*/
|
|
2742
|
+
get authedAs() {
|
|
2743
|
+
return this.connectivity.authedAs;
|
|
2744
|
+
}
|
|
2727
2745
|
/**
|
|
2728
2746
|
* Answers the relay's NIP-42 challenge with this relay's auth policy (or the
|
|
2729
2747
|
* NDK default). Resolves true once the relay accepts, false otherwise.
|
|
@@ -3784,13 +3802,13 @@ function signatureVerificationInit(w) {
|
|
|
3784
3802
|
msg.data,
|
|
3785
3803
|
"\n\n\u{1F50D} This likely means:",
|
|
3786
3804
|
"\n 1. You have a STALE worker.js file that needs updating",
|
|
3787
|
-
"\n 2. Version mismatch between @
|
|
3805
|
+
"\n 2. Version mismatch between @bzzsocial/ndk and deployed worker",
|
|
3788
3806
|
"\n 3. Wrong worker is being used for signature verification",
|
|
3789
3807
|
"\n\n\u2705 Solution: Update your worker files:",
|
|
3790
|
-
"\n cp node_modules/@
|
|
3808
|
+
"\n cp node_modules/@bzzsocial/ndk/dist/workers/sig-verification.js public/",
|
|
3791
3809
|
"\n cp node_modules/@nostr-dev-kit/cache-sqlite-wasm/dist/worker.js public/",
|
|
3792
3810
|
"\n\n\u{1F4A1} Or use Vite/bundler imports instead of static files:",
|
|
3793
|
-
'\n import SigWorker from "@
|
|
3811
|
+
'\n import SigWorker from "@bzzsocial/ndk/workers/sig-verification?worker"'
|
|
3794
3812
|
);
|
|
3795
3813
|
return;
|
|
3796
3814
|
}
|
|
@@ -10781,7 +10799,7 @@ No events can match this time range!`,
|
|
|
10781
10799
|
guards.error(
|
|
10782
10800
|
GuardrailCheckId.FILTER_BECH32_IN_ARRAY,
|
|
10783
10801
|
`Filter[${filterIndex}].ids[${idx}] contains bech32: "${id}". IDs must be hex, not bech32.`,
|
|
10784
|
-
`Use filterFromId() to decode bech32 first: import { filterFromId } from "@
|
|
10802
|
+
`Use filterFromId() to decode bech32 first: import { filterFromId } from "@bzzsocial/ndk"`,
|
|
10785
10803
|
false
|
|
10786
10804
|
// Fatal error - cannot be disabled
|
|
10787
10805
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bzzsocial/ndk",
|
|
3
|
-
"version": "3.0.3-bzz.
|
|
3
|
+
"version": "3.0.3-bzz.8",
|
|
4
4
|
"description": "NDK - Nostr Development Kit. Includes AI Guardrails to catch common mistakes during development.",
|
|
5
5
|
"homepage": "https://github.com/bzzsocial/ndk/tree/bzz/core#readme",
|
|
6
6
|
"repository": {
|
|
@@ -194,4 +194,31 @@ describe("AUTH on demand", () => {
|
|
|
194
194
|
await vi.waitFor(() => expect(failed).toHaveBeenCalled());
|
|
195
195
|
expect(relay.status).toBe(NDKRelayStatus.CONNECTED);
|
|
196
196
|
});
|
|
197
|
+
|
|
198
|
+
it("settles every attempt, a quietly declined offer included", async () => {
|
|
199
|
+
const { policy } = onDemandPolicy();
|
|
200
|
+
const r = connectedRelay(policy);
|
|
201
|
+
const settled = vi.fn();
|
|
202
|
+
r.relay.on("auth:settled", settled);
|
|
203
|
+
|
|
204
|
+
r.recv(["AUTH", "c1"]);
|
|
205
|
+
await tick();
|
|
206
|
+
expect(settled.mock.lastCall?.[0]).toBe(false);
|
|
207
|
+
|
|
208
|
+
const authed = r.relay.authenticate("manual");
|
|
209
|
+
await acceptAuth(r);
|
|
210
|
+
await expect(authed).resolves.toBe(true);
|
|
211
|
+
expect(settled.mock.lastCall?.[0]).toBe(true);
|
|
212
|
+
expect(settled).toHaveBeenCalledTimes(2);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it("records whom the connection signed in as, until it closes", async () => {
|
|
216
|
+
const r = connectedRelay(async () => true);
|
|
217
|
+
r.recv(["AUTH", "c1"]);
|
|
218
|
+
await acceptAuth(r);
|
|
219
|
+
expect(r.relay.authedAs).toBe((await r.ndk.signer!.user()).pubkey);
|
|
220
|
+
|
|
221
|
+
(r.relay.connectivity as any).onDisconnect();
|
|
222
|
+
expect(r.relay.authedAs).toBeUndefined();
|
|
223
|
+
});
|
|
197
224
|
});
|
|
@@ -58,6 +58,8 @@ export class NDKRelayConnectivity {
|
|
|
58
58
|
|
|
59
59
|
/** The latest NIP-42 challenge on the current connection. */
|
|
60
60
|
public authChallenge?: string;
|
|
61
|
+
/** The pubkey this connection is signed in as (NIP-42), until the connection closes. */
|
|
62
|
+
public authedAs?: string;
|
|
61
63
|
private authInFlight?: Promise<boolean>;
|
|
62
64
|
/** How long to wait for the relay's OK on an AUTH event, and for a signer to sign it. */
|
|
63
65
|
public authTimeoutMs = 10_000;
|
|
@@ -329,6 +331,7 @@ export class NDKRelayConnectivity {
|
|
|
329
331
|
this.updateConnectionStats.connected();
|
|
330
332
|
this._status = NDKRelayStatus.CONNECTED;
|
|
331
333
|
this.authChallenge = undefined;
|
|
334
|
+
this.authedAs = undefined;
|
|
332
335
|
this.authWanted = undefined;
|
|
333
336
|
|
|
334
337
|
// disconnect() stops monitoring; a new connection needs it again
|
|
@@ -370,6 +373,7 @@ export class NDKRelayConnectivity {
|
|
|
370
373
|
}
|
|
371
374
|
this._status = NDKRelayStatus.DISCONNECTED;
|
|
372
375
|
this.authChallenge = undefined;
|
|
376
|
+
this.authedAs = undefined;
|
|
373
377
|
this.authWanted = undefined;
|
|
374
378
|
this.ndkRelay.emit("disconnect");
|
|
375
379
|
}
|
|
@@ -609,6 +613,18 @@ export class NDKRelayConnectivity {
|
|
|
609
613
|
authPolicy: NonNullable<NDKRelay["authPolicy"]>,
|
|
610
614
|
challenge: string,
|
|
611
615
|
reason: NDKAuthReason,
|
|
616
|
+
): Promise<boolean> {
|
|
617
|
+
const authed = await this.attemptAuth(authPolicy, challenge, reason);
|
|
618
|
+
// Every attempt ends here, however it ended (a quietly declined offer and a connection
|
|
619
|
+
// that changed underneath included), for whoever waits on the outcome.
|
|
620
|
+
this.ndkRelay.emit("auth:settled", authed);
|
|
621
|
+
return authed;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
private async attemptAuth(
|
|
625
|
+
authPolicy: NonNullable<NDKRelay["authPolicy"]>,
|
|
626
|
+
challenge: string,
|
|
627
|
+
reason: NDKAuthReason,
|
|
612
628
|
): Promise<boolean> {
|
|
613
629
|
this._status = NDKRelayStatus.AUTHENTICATING;
|
|
614
630
|
|
|
@@ -631,6 +647,7 @@ export class NDKRelayConnectivity {
|
|
|
631
647
|
if (this.authChallenge !== challenge || !this.connected) return false;
|
|
632
648
|
|
|
633
649
|
this._status = NDKRelayStatus.AUTHENTICATED;
|
|
650
|
+
this.authedAs = res.pubkey;
|
|
634
651
|
this.debug("Authentication successful");
|
|
635
652
|
this.ndkRelay.emit("authed");
|
|
636
653
|
this.retryPendingAuthPublishes();
|
package/src/relay/index.ts
CHANGED
|
@@ -85,6 +85,7 @@ export interface NDKRelayConnectionStats {
|
|
|
85
85
|
* @emits NDKRelay#eose when the relay has reached the end of stored events
|
|
86
86
|
* @emits NDKRelay#auth when the relay requires authentication
|
|
87
87
|
* @emits NDKRelay#authed when the relay has authenticated
|
|
88
|
+
* @emits NDKRelay#auth:settled when an AUTH attempt ends, whichever way (true: signed in)
|
|
88
89
|
* @emits NDKRelay#delayed-connect when the relay will wait before reconnecting
|
|
89
90
|
*/
|
|
90
91
|
export class NDKRelay extends EventEmitter<{
|
|
@@ -100,6 +101,7 @@ export class NDKRelay extends EventEmitter<{
|
|
|
100
101
|
auth: (challenge: string) => void;
|
|
101
102
|
authed: () => void;
|
|
102
103
|
"auth:failed": (error: Error) => void;
|
|
104
|
+
"auth:settled": (authed: boolean) => void;
|
|
103
105
|
published: (event: NDKEvent) => void;
|
|
104
106
|
"publish:failed": (event: NDKEvent, error: Error) => void;
|
|
105
107
|
"delayed-connect": (delayInMs: number) => void;
|
|
@@ -228,6 +230,14 @@ export class NDKRelay extends EventEmitter<{
|
|
|
228
230
|
return this.connectivity.authChallenge;
|
|
229
231
|
}
|
|
230
232
|
|
|
233
|
+
/**
|
|
234
|
+
* The pubkey the current connection is signed in as (NIP-42), if it is. Cleared when the
|
|
235
|
+
* connection closes: a new one signs in afresh.
|
|
236
|
+
*/
|
|
237
|
+
get authedAs(): string | undefined {
|
|
238
|
+
return this.connectivity.authedAs;
|
|
239
|
+
}
|
|
240
|
+
|
|
231
241
|
/**
|
|
232
242
|
* Answers the relay's NIP-42 challenge with this relay's auth policy (or the
|
|
233
243
|
* NDK default). Resolves true once the relay accepts, false otherwise.
|