@nostrify/nostrify 0.46.4
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/.turbo/turbo-build.log +5 -0
- package/BunkerURI.test.ts +28 -0
- package/BunkerURI.ts +58 -0
- package/CHANGELOG.md +562 -0
- package/LICENSE +21 -0
- package/NBrowserSigner.test.ts +170 -0
- package/NBrowserSigner.ts +100 -0
- package/NCache.bench.ts +81 -0
- package/NCache.test.ts +22 -0
- package/NCache.ts +73 -0
- package/NConnectSigner.test.ts +102 -0
- package/NConnectSigner.ts +189 -0
- package/NIP05.test.ts +67 -0
- package/NIP05.ts +52 -0
- package/NIP50.test.ts +58 -0
- package/NIP50.ts +24 -0
- package/NIP98.test.ts +181 -0
- package/NIP98.ts +97 -0
- package/NKinds.test.ts +42 -0
- package/NKinds.ts +26 -0
- package/NPool.test.ts +117 -0
- package/NPool.ts +224 -0
- package/NRelay1.test.ts +174 -0
- package/NRelay1.ts +440 -0
- package/NSchema.test.ts +94 -0
- package/NSchema.ts +255 -0
- package/NSecSigner.bench.ts +55 -0
- package/NSecSigner.test.ts +26 -0
- package/NSecSigner.ts +60 -0
- package/NSet.bench.ts +10 -0
- package/NSet.test.ts +92 -0
- package/NSet.ts +203 -0
- package/README.md +314 -0
- package/RelayError.test.ts +23 -0
- package/RelayError.ts +22 -0
- package/dist/BunkerURI.d.ts +23 -0
- package/dist/BunkerURI.d.ts.map +1 -0
- package/dist/BunkerURI.js +52 -0
- package/dist/BunkerURI.js.map +1 -0
- package/dist/NBrowserSigner.d.ts +27 -0
- package/dist/NBrowserSigner.d.ts.map +1 -0
- package/dist/NBrowserSigner.js +96 -0
- package/dist/NBrowserSigner.js.map +1 -0
- package/dist/NCache.d.ts +34 -0
- package/dist/NCache.d.ts.map +1 -0
- package/dist/NCache.js +63 -0
- package/dist/NCache.js.map +1 -0
- package/dist/NConnectSigner.d.ts +50 -0
- package/dist/NConnectSigner.d.ts.map +1 -0
- package/dist/NConnectSigner.js +130 -0
- package/dist/NConnectSigner.js.map +1 -0
- package/dist/NIP05.d.ts +15 -0
- package/dist/NIP05.d.ts.map +1 -0
- package/dist/NIP05.js +40 -0
- package/dist/NIP05.js.map +1 -0
- package/dist/NIP50.d.ts +10 -0
- package/dist/NIP50.d.ts.map +1 -0
- package/dist/NIP50.js +26 -0
- package/dist/NIP50.js.map +1 -0
- package/dist/NIP98.d.ts +15 -0
- package/dist/NIP98.d.ts.map +1 -0
- package/dist/NIP98.js +71 -0
- package/dist/NIP98.js.map +1 -0
- package/dist/NKinds.d.ts +13 -0
- package/dist/NKinds.d.ts.map +1 -0
- package/dist/NKinds.js +27 -0
- package/dist/NKinds.js.map +1 -0
- package/dist/NPool.d.ts +91 -0
- package/dist/NPool.d.ts.map +1 -0
- package/dist/NPool.js +185 -0
- package/dist/NPool.js.map +1 -0
- package/dist/NRelay1.d.ts +80 -0
- package/dist/NRelay1.d.ts.map +1 -0
- package/dist/NRelay1.js +336 -0
- package/dist/NRelay1.js.map +1 -0
- package/dist/NSchema.d.ts +73 -0
- package/dist/NSchema.d.ts.map +1 -0
- package/dist/NSchema.js +215 -0
- package/dist/NSchema.js.map +1 -0
- package/dist/NSecSigner.d.ts +29 -0
- package/dist/NSecSigner.d.ts.map +1 -0
- package/dist/NSecSigner.js +52 -0
- package/dist/NSecSigner.js.map +1 -0
- package/dist/NSet.d.ts +76 -0
- package/dist/NSet.d.ts.map +1 -0
- package/dist/NSet.js +174 -0
- package/dist/NSet.js.map +1 -0
- package/dist/RelayError.d.ts +10 -0
- package/dist/RelayError.d.ts.map +1 -0
- package/dist/RelayError.js +23 -0
- package/dist/RelayError.js.map +1 -0
- package/dist/ln/LNURL.d.ts +55 -0
- package/dist/ln/LNURL.d.ts.map +1 -0
- package/dist/ln/LNURL.js +105 -0
- package/dist/ln/LNURL.js.map +1 -0
- package/dist/ln/mod.d.ts +4 -0
- package/dist/ln/mod.d.ts.map +1 -0
- package/dist/ln/mod.js +6 -0
- package/dist/ln/mod.js.map +1 -0
- package/dist/ln/types/LNURLCallback.d.ts +8 -0
- package/dist/ln/types/LNURLCallback.d.ts.map +1 -0
- package/dist/ln/types/LNURLCallback.js +3 -0
- package/dist/ln/types/LNURLCallback.js.map +1 -0
- package/dist/ln/types/LNURLDetails.d.ts +20 -0
- package/dist/ln/types/LNURLDetails.d.ts.map +1 -0
- package/dist/ln/types/LNURLDetails.js +3 -0
- package/dist/ln/types/LNURLDetails.js.map +1 -0
- package/dist/mod.d.ts +16 -0
- package/dist/mod.d.ts.map +1 -0
- package/dist/mod.js +32 -0
- package/dist/mod.js.map +1 -0
- package/dist/test/ErrorRelay.d.ts +21 -0
- package/dist/test/ErrorRelay.d.ts.map +1 -0
- package/dist/test/ErrorRelay.js +26 -0
- package/dist/test/ErrorRelay.js.map +1 -0
- package/dist/test/MockRelay.d.ts +20 -0
- package/dist/test/MockRelay.d.ts.map +1 -0
- package/dist/test/MockRelay.js +66 -0
- package/dist/test/MockRelay.js.map +1 -0
- package/dist/test/TestRelayServer.d.ts +25 -0
- package/dist/test/TestRelayServer.d.ts.map +1 -0
- package/dist/test/TestRelayServer.js +134 -0
- package/dist/test/TestRelayServer.js.map +1 -0
- package/dist/test/mod.d.ts +8 -0
- package/dist/test/mod.d.ts.map +1 -0
- package/dist/test/mod.js +28 -0
- package/dist/test/mod.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/uploaders/BlossomUploader.d.ts +26 -0
- package/dist/uploaders/BlossomUploader.d.ts.map +1 -0
- package/dist/uploaders/BlossomUploader.js +71 -0
- package/dist/uploaders/BlossomUploader.js.map +1 -0
- package/dist/uploaders/NostrBuildUploader.d.ts +24 -0
- package/dist/uploaders/NostrBuildUploader.d.ts.map +1 -0
- package/dist/uploaders/NostrBuildUploader.js +67 -0
- package/dist/uploaders/NostrBuildUploader.js.map +1 -0
- package/dist/uploaders/mod.d.ts +3 -0
- package/dist/uploaders/mod.d.ts.map +1 -0
- package/dist/uploaders/mod.js +8 -0
- package/dist/uploaders/mod.js.map +1 -0
- package/dist/utils/CircularSet.d.ts +13 -0
- package/dist/utils/CircularSet.d.ts.map +1 -0
- package/dist/utils/CircularSet.js +35 -0
- package/dist/utils/CircularSet.js.map +1 -0
- package/dist/utils/Machina.d.ts +36 -0
- package/dist/utils/Machina.d.ts.map +1 -0
- package/dist/utils/Machina.js +66 -0
- package/dist/utils/Machina.js.map +1 -0
- package/dist/utils/N64.d.ts +9 -0
- package/dist/utils/N64.d.ts.map +1 -0
- package/dist/utils/N64.js +23 -0
- package/dist/utils/N64.js.map +1 -0
- package/dist/utils/mod.d.ts +3 -0
- package/dist/utils/mod.d.ts.map +1 -0
- package/dist/utils/mod.js +8 -0
- package/dist/utils/mod.js.map +1 -0
- package/ln/LNURL.test.ts +87 -0
- package/ln/LNURL.ts +146 -0
- package/ln/mod.ts +4 -0
- package/ln/types/LNURLCallback.ts +7 -0
- package/ln/types/LNURLDetails.ts +19 -0
- package/mod.ts +16 -0
- package/package.json +23 -0
- package/test/ErrorRelay.test.ts +19 -0
- package/test/ErrorRelay.ts +40 -0
- package/test/MockRelay.test.ts +20 -0
- package/test/MockRelay.ts +92 -0
- package/test/TestRelayServer.ts +156 -0
- package/test/mod.ts +28 -0
- package/tsconfig.json +14 -0
- package/uploaders/BlossomUploader.test.ts +26 -0
- package/uploaders/BlossomUploader.ts +98 -0
- package/uploaders/NostrBuildUploader.test.ts +22 -0
- package/uploaders/NostrBuildUploader.ts +89 -0
- package/uploaders/mod.ts +2 -0
- package/utils/CircularSet.test.ts +15 -0
- package/utils/CircularSet.ts +34 -0
- package/utils/Machina.test.ts +91 -0
- package/utils/Machina.ts +66 -0
- package/utils/N64.test.ts +27 -0
- package/utils/N64.ts +23 -0
- package/utils/mod.ts +2 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.js","sourceRoot":"","sources":["../../uploaders/mod.ts"],"names":[],"mappings":";;;AAAA,qDAAoD;AAA3C,kHAAA,eAAe,OAAA;AACxB,2DAA0D;AAAjD,wHAAA,kBAAkB,OAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Like a Circular Buffer, but the values are deduplicated.
|
|
3
|
+
* Shares the properties of both a Circular Buffer and a Set.
|
|
4
|
+
*/
|
|
5
|
+
export declare class CircularSet<T> {
|
|
6
|
+
private capacity;
|
|
7
|
+
private set;
|
|
8
|
+
constructor(capacity: number);
|
|
9
|
+
add(item: T): void;
|
|
10
|
+
has(item: T): boolean;
|
|
11
|
+
[Symbol.iterator](): Iterator<T>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=CircularSet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CircularSet.d.ts","sourceRoot":"","sources":["../../utils/CircularSet.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,WAAW,CAAC,CAAC;IAGZ,OAAO,CAAC,QAAQ;IAF5B,OAAO,CAAC,GAAG,CAAS;gBAEA,QAAQ,EAAE,MAAM;IAIpC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAelB,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO;IAIrB,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC;CAGjC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CircularSet = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Like a Circular Buffer, but the values are deduplicated.
|
|
6
|
+
* Shares the properties of both a Circular Buffer and a Set.
|
|
7
|
+
*/
|
|
8
|
+
class CircularSet {
|
|
9
|
+
capacity;
|
|
10
|
+
set;
|
|
11
|
+
constructor(capacity) {
|
|
12
|
+
this.capacity = capacity;
|
|
13
|
+
this.set = new Set();
|
|
14
|
+
}
|
|
15
|
+
add(item) {
|
|
16
|
+
if (this.set.has(item)) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (this.set.size >= this.capacity) {
|
|
20
|
+
const oldest = this.set.values().next().value;
|
|
21
|
+
if (oldest) {
|
|
22
|
+
this.set.delete(oldest);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
this.set.add(item);
|
|
26
|
+
}
|
|
27
|
+
has(item) {
|
|
28
|
+
return this.set.has(item);
|
|
29
|
+
}
|
|
30
|
+
[Symbol.iterator]() {
|
|
31
|
+
return this.set.values();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.CircularSet = CircularSet;
|
|
35
|
+
//# sourceMappingURL=CircularSet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CircularSet.js","sourceRoot":"","sources":["../../utils/CircularSet.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,MAAa,WAAW;IAGF;IAFZ,GAAG,CAAS;IAEpB,YAAoB,QAAgB;QAAhB,aAAQ,GAAR,QAAQ,CAAQ;QAClC,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;IACvB,CAAC;IAED,GAAG,CAAC,IAAO;QACT,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YAC9C,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IAED,GAAG,CAAC,IAAO;QACT,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,CAAC,MAAM,CAAC,QAAQ,CAAC;QACf,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;IAC3B,CAAC;CACF;AA7BD,kCA6BC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infinite async generator. Iterates messages pushed to it until closed.
|
|
3
|
+
* Only one consumer is expected to use a Machina instance at a time.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* // Create the Machina instance
|
|
8
|
+
* const machina = new Machina<string>();
|
|
9
|
+
*
|
|
10
|
+
* // Async generator loop
|
|
11
|
+
* async function getMessages() {
|
|
12
|
+
* for await (const msg of machina.stream()) {
|
|
13
|
+
* console.log(msg);
|
|
14
|
+
* }
|
|
15
|
+
* }
|
|
16
|
+
*
|
|
17
|
+
* // Start the generator
|
|
18
|
+
* getMessages();
|
|
19
|
+
*
|
|
20
|
+
* // Push messages to it
|
|
21
|
+
* machina.push('hello!');
|
|
22
|
+
* machina.push('whats up?');
|
|
23
|
+
* machina.push('greetings');
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare class Machina<T> implements AsyncIterable<T> {
|
|
27
|
+
#private;
|
|
28
|
+
constructor(signal?: AbortSignal);
|
|
29
|
+
/** Get messages as an AsyncIterable. */
|
|
30
|
+
[Symbol.asyncIterator](): AsyncIterator<T>;
|
|
31
|
+
/** Push a message into the Machina instance, making it available to the consumer of `stream()`. */
|
|
32
|
+
push(data: T): void;
|
|
33
|
+
/** Stops streaming and throws an error to the consumer. */
|
|
34
|
+
private abort;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=Machina.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Machina.d.ts","sourceRoot":"","sources":["../../utils/Machina.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,OAAO,CAAC,CAAC,CAAE,YAAW,aAAa,CAAC,CAAC,CAAC;;gBAKrC,MAAM,CAAC,EAAE,WAAW;IAQhC,wCAAwC;IACjC,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC;IAejD,mGAAmG;IACnG,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAKnB,2DAA2D;IAC3D,OAAO,CAAC,KAAK;CAId"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Machina = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Infinite async generator. Iterates messages pushed to it until closed.
|
|
6
|
+
* Only one consumer is expected to use a Machina instance at a time.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* // Create the Machina instance
|
|
11
|
+
* const machina = new Machina<string>();
|
|
12
|
+
*
|
|
13
|
+
* // Async generator loop
|
|
14
|
+
* async function getMessages() {
|
|
15
|
+
* for await (const msg of machina.stream()) {
|
|
16
|
+
* console.log(msg);
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* // Start the generator
|
|
21
|
+
* getMessages();
|
|
22
|
+
*
|
|
23
|
+
* // Push messages to it
|
|
24
|
+
* machina.push('hello!');
|
|
25
|
+
* machina.push('whats up?');
|
|
26
|
+
* machina.push('greetings');
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
class Machina {
|
|
30
|
+
#queue = [];
|
|
31
|
+
#resolve;
|
|
32
|
+
#aborted = false;
|
|
33
|
+
constructor(signal) {
|
|
34
|
+
if (signal?.aborted) {
|
|
35
|
+
this.abort();
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
signal?.addEventListener('abort', () => this.abort(), { once: true });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Get messages as an AsyncIterable. */
|
|
42
|
+
async *[Symbol.asyncIterator]() {
|
|
43
|
+
while (!this.#aborted) {
|
|
44
|
+
if (this.#queue.length) {
|
|
45
|
+
yield this.#queue.shift();
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
await new Promise((_resolve) => {
|
|
49
|
+
this.#resolve = _resolve;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
throw new DOMException('The signal has been aborted', 'AbortError');
|
|
53
|
+
}
|
|
54
|
+
/** Push a message into the Machina instance, making it available to the consumer of `stream()`. */
|
|
55
|
+
push(data) {
|
|
56
|
+
this.#queue.push(data);
|
|
57
|
+
this.#resolve?.();
|
|
58
|
+
}
|
|
59
|
+
/** Stops streaming and throws an error to the consumer. */
|
|
60
|
+
abort() {
|
|
61
|
+
this.#aborted = true;
|
|
62
|
+
this.#resolve?.();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.Machina = Machina;
|
|
66
|
+
//# sourceMappingURL=Machina.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Machina.js","sourceRoot":"","sources":["../../utils/Machina.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAa,OAAO;IAClB,MAAM,GAAQ,EAAE,CAAC;IACjB,QAAQ,CAA2B;IACnC,QAAQ,GAAG,KAAK,CAAC;IAEjB,YAAY,MAAoB;QAC9B,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IAED,wCAAwC;IACxC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACtB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACvB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAO,CAAC;gBAC/B,SAAS;YACX,CAAC;YAED,MAAM,IAAI,OAAO,CAAO,CAAC,QAAQ,EAAE,EAAE;gBACnC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAC3B,CAAC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,IAAI,YAAY,CAAC,6BAA6B,EAAE,YAAY,CAAC,CAAC;IACtE,CAAC;IAED,mGAAmG;IACnG,IAAI,CAAC,IAAO;QACV,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvB,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;IACpB,CAAC;IAED,2DAA2D;IACnD,KAAK;QACX,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;IACpB,CAAC;CACF;AAxCD,0BAwCC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { NostrEvent } from '@nostrify/types';
|
|
2
|
+
/** Nostr base64 helper utilities. */
|
|
3
|
+
export declare class N64 {
|
|
4
|
+
/** Encode an event as a base64 string. */
|
|
5
|
+
static encodeEvent(event: NostrEvent): string;
|
|
6
|
+
/** Decode an event from a base64 string. Validates the event's structure but does not verify its signature. */
|
|
7
|
+
static decodeEvent(base64: string): NostrEvent;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=N64.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"N64.d.ts","sourceRoot":"","sources":["../../utils/N64.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAK7C,qCAAqC;AACrC,qBAAa,GAAG;IACd,0CAA0C;IAC1C,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM;IAI7C,+GAA+G;IAC/G,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU;CAS/C"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.N64 = void 0;
|
|
4
|
+
const base64_1 = require("@std/encoding/base64");
|
|
5
|
+
const NSchema_1 = require("../NSchema");
|
|
6
|
+
/** Nostr base64 helper utilities. */
|
|
7
|
+
class N64 {
|
|
8
|
+
/** Encode an event as a base64 string. */
|
|
9
|
+
static encodeEvent(event) {
|
|
10
|
+
return (0, base64_1.encodeBase64)(JSON.stringify(event));
|
|
11
|
+
}
|
|
12
|
+
/** Decode an event from a base64 string. Validates the event's structure but does not verify its signature. */
|
|
13
|
+
static decodeEvent(base64) {
|
|
14
|
+
const bytes = (0, base64_1.decodeBase64)(base64);
|
|
15
|
+
const text = new TextDecoder().decode(bytes);
|
|
16
|
+
return NSchema_1.NSchema
|
|
17
|
+
.json()
|
|
18
|
+
.pipe(NSchema_1.NSchema.event())
|
|
19
|
+
.parse(text);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.N64 = N64;
|
|
23
|
+
//# sourceMappingURL=N64.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"N64.js","sourceRoot":"","sources":["../../utils/N64.ts"],"names":[],"mappings":";;;AACA,iDAAkE;AAElE,wCAA0C;AAE1C,qCAAqC;AACrC,MAAa,GAAG;IACd,0CAA0C;IAC1C,MAAM,CAAC,WAAW,CAAC,KAAiB;QAClC,OAAO,IAAA,qBAAY,EAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,+GAA+G;IAC/G,MAAM,CAAC,WAAW,CAAC,MAAc;QAC/B,MAAM,KAAK,GAAG,IAAA,qBAAY,EAAC,MAAM,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAE7C,OAAO,iBAAC;aACL,IAAI,EAAE;aACN,IAAI,CAAC,iBAAC,CAAC,KAAK,EAAE,CAAC;aACf,KAAK,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;CACF;AAhBD,kBAgBC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../utils/mod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.N64 = exports.Machina = void 0;
|
|
4
|
+
var Machina_1 = require("./Machina");
|
|
5
|
+
Object.defineProperty(exports, "Machina", { enumerable: true, get: function () { return Machina_1.Machina; } });
|
|
6
|
+
var N64_1 = require("./N64");
|
|
7
|
+
Object.defineProperty(exports, "N64", { enumerable: true, get: function () { return N64_1.N64; } });
|
|
8
|
+
//# sourceMappingURL=mod.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.js","sourceRoot":"","sources":["../../utils/mod.ts"],"names":[],"mappings":";;;AAAA,qCAAoC;AAA3B,kGAAA,OAAO,OAAA;AAChB,6BAA4B;AAAnB,0FAAA,GAAG,OAAA"}
|
package/ln/LNURL.test.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { assertEquals } from '@std/assert';
|
|
2
|
+
|
|
3
|
+
import { LNURL } from './LNURL.ts';
|
|
4
|
+
|
|
5
|
+
// deno-lint-ignore require-await
|
|
6
|
+
const mockFetch: typeof globalThis.fetch = async (input, init) => {
|
|
7
|
+
const { url } = new Request(input, init);
|
|
8
|
+
switch (url) {
|
|
9
|
+
case 'https://getalby.com/.well-known/lnurlp/alexgleason':
|
|
10
|
+
return new Response(JSON.stringify({
|
|
11
|
+
status: 'OK',
|
|
12
|
+
tag: 'payRequest',
|
|
13
|
+
commentAllowed: 255,
|
|
14
|
+
callback: 'https://getalby.com/lnurlp/alexgleason/callback',
|
|
15
|
+
metadata: '[["text/identifier","alexgleason@getalby.com"],["text/plain","Sats for alexgleason"]]',
|
|
16
|
+
minSendable: 1000,
|
|
17
|
+
maxSendable: 100000000,
|
|
18
|
+
payerData: {
|
|
19
|
+
name: { mandatory: false },
|
|
20
|
+
email: { mandatory: false },
|
|
21
|
+
pubkey: { mandatory: false },
|
|
22
|
+
},
|
|
23
|
+
nostrPubkey: '79f00d3f5a19ec806189fcab03c1be4ff81d18ee4f653c88fac41fe03570f432',
|
|
24
|
+
allowsNostr: true,
|
|
25
|
+
}));
|
|
26
|
+
case 'https://getalby.com/lnurlp/alexgleason/callback?amount=1000&lnurl=lnurl1dp68gurn8ghj7em9w3skccne9e3k7mf09emk2mrv944kummhdchkcmn4wfk8qtmpd3jhsemvv4shxmmw5uhvxu':
|
|
27
|
+
return new Response(JSON.stringify({
|
|
28
|
+
status: 'OK',
|
|
29
|
+
successAction: { tag: 'message', message: 'Thanks, sats received!' },
|
|
30
|
+
verify: 'https://getalby.com/lnurlp/alexgleason/verify/sMgdHth68xnS5H1tJtL4kh3T',
|
|
31
|
+
routes: [],
|
|
32
|
+
pr:
|
|
33
|
+
'lnbc10n1pj6a3pmpp54wsjl3nscygnfsf6uy08cnlf94t64a7cr0pt3t6nmdzm4kq8x6yshp5nf3ugrnz5d5fc5avnrzu8m9ae3e7p4v82cyhtf425dmtv8fn755qcqzzsxqyz5vqsp5m9d6yrj9mu5wwk3kxfdn4hwwmztdjqvdc3z5402gwdc6janx4ltq9qyyssq36wz68vj35pr39e8hkq0ldfauglqfsfyw9u0u4v4dmy7hvg20244jm69ja4g0cmwzxxgmzrqqsgeenxzmsqwhpfrzk7dvezd60u0qcqpd6nhs7',
|
|
34
|
+
}));
|
|
35
|
+
default:
|
|
36
|
+
throw new Error(`Unexpected URL: ${url}`);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
Deno.test('LNURL', async (t) => {
|
|
41
|
+
await t.step('fromString', () => {
|
|
42
|
+
const lnurl = LNURL.fromString(
|
|
43
|
+
'lnurl1dp68gurn8ghj7em9w3skccne9e3k7mf09emk2mrv944kummhdchkcmn4wfk8qtmpd3jhsemvv4shxmmw5uhvxu',
|
|
44
|
+
);
|
|
45
|
+
assertEquals(lnurl.url.toString(), 'https://getalby.com/.well-known/lnurlp/alexgleason');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
await t.step('fromLightningAddress', () => {
|
|
49
|
+
const lnurl = LNURL.fromLightningAddress('alexgleason@getalby.com');
|
|
50
|
+
assertEquals(lnurl.url.toString(), 'https://getalby.com/.well-known/lnurlp/alexgleason');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
await t.step('toString', () => {
|
|
54
|
+
const lnurl = new LNURL(new URL('https://getalby.com/.well-known/lnurlp/alexgleason'));
|
|
55
|
+
assertEquals(
|
|
56
|
+
lnurl.toString(),
|
|
57
|
+
'lnurl1dp68gurn8ghj7em9w3skccne9e3k7mf09emk2mrv944kummhdchkcmn4wfk8qtmpd3jhsemvv4shxmmw5uhvxu',
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
await t.step('getDetails', async () => {
|
|
62
|
+
const lnurl = new LNURL(new URL('https://getalby.com/.well-known/lnurlp/alexgleason'), { fetch: mockFetch });
|
|
63
|
+
const details = await lnurl.getDetails();
|
|
64
|
+
|
|
65
|
+
assertEquals(details, {
|
|
66
|
+
tag: 'payRequest',
|
|
67
|
+
commentAllowed: 255,
|
|
68
|
+
callback: 'https://getalby.com/lnurlp/alexgleason/callback',
|
|
69
|
+
metadata: '[["text/identifier","alexgleason@getalby.com"],["text/plain","Sats for alexgleason"]]',
|
|
70
|
+
minSendable: 1000,
|
|
71
|
+
maxSendable: 100000000,
|
|
72
|
+
nostrPubkey: '79f00d3f5a19ec806189fcab03c1be4ff81d18ee4f653c88fac41fe03570f432',
|
|
73
|
+
allowsNostr: true,
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
await t.step('getInvoice', async () => {
|
|
78
|
+
const lnurl = new LNURL(new URL('https://getalby.com/.well-known/lnurlp/alexgleason'), { fetch: mockFetch });
|
|
79
|
+
const invoice = await lnurl.getInvoice({ amount: 1000 });
|
|
80
|
+
|
|
81
|
+
assertEquals(invoice, {
|
|
82
|
+
pr:
|
|
83
|
+
'lnbc10n1pj6a3pmpp54wsjl3nscygnfsf6uy08cnlf94t64a7cr0pt3t6nmdzm4kq8x6yshp5nf3ugrnz5d5fc5avnrzu8m9ae3e7p4v82cyhtf425dmtv8fn755qcqzzsxqyz5vqsp5m9d6yrj9mu5wwk3kxfdn4hwwmztdjqvdc3z5402gwdc6janx4ltq9qyyssq36wz68vj35pr39e8hkq0ldfauglqfsfyw9u0u4v4dmy7hvg20244jm69ja4g0cmwzxxgmzrqqsgeenxzmsqwhpfrzk7dvezd60u0qcqpd6nhs7',
|
|
84
|
+
routes: [],
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
package/ln/LNURL.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { NostrEvent } from "@nostrify/types";
|
|
2
|
+
import { bech32 } from "@scure/base";
|
|
3
|
+
|
|
4
|
+
import { LNURLCallback } from "./types/LNURLCallback";
|
|
5
|
+
import { LNURLDetails } from "./types/LNURLDetails";
|
|
6
|
+
|
|
7
|
+
import { NSchema as n, z } from "../NSchema";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Represents an LNURL, with methods to fetch details and generate invoices.
|
|
11
|
+
*/
|
|
12
|
+
export class LNURL {
|
|
13
|
+
/** Underlying HTTP(s) URL of the user. */
|
|
14
|
+
readonly url: URL;
|
|
15
|
+
/** Fetch function to use for HTTP requests. */
|
|
16
|
+
private fetch: typeof globalThis.fetch;
|
|
17
|
+
|
|
18
|
+
constructor(
|
|
19
|
+
/** Underlying HTTP(s) URL of the user. */
|
|
20
|
+
url: URL,
|
|
21
|
+
/** Options for the LNURL class. */
|
|
22
|
+
opts?: {
|
|
23
|
+
/** Fetch function to use for HTTP requests. */
|
|
24
|
+
fetch: typeof globalThis.fetch;
|
|
25
|
+
},
|
|
26
|
+
) {
|
|
27
|
+
this.url = url;
|
|
28
|
+
this.fetch = opts?.fetch ?? globalThis.fetch.bind(globalThis);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Create an LNURL object from a bech32 `lnurl1...` string.
|
|
33
|
+
* Throws if the value is not a valid lnurl.
|
|
34
|
+
*/
|
|
35
|
+
static fromString(
|
|
36
|
+
value: string,
|
|
37
|
+
opts?: { fetch: typeof globalThis.fetch },
|
|
38
|
+
): LNURL {
|
|
39
|
+
if (!n.bech32().safeParse(value).success) {
|
|
40
|
+
throw new Error('Expected a bech32 string starting with "lnurl1"');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const { prefix, words } = bech32.decode(
|
|
44
|
+
value as `${string}1${string}`,
|
|
45
|
+
20000,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
if (prefix !== "lnurl") {
|
|
49
|
+
throw new Error('Expected a bech32 string starting with "lnurl1"');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const data = bech32.fromWords(words);
|
|
53
|
+
const url = new URL(new TextDecoder().decode(data));
|
|
54
|
+
|
|
55
|
+
return new LNURL(url, opts);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Create an LNURL object from a lightning address (email-like format).
|
|
60
|
+
* Throws if the value is not a valid lightning address.
|
|
61
|
+
*/
|
|
62
|
+
static fromLightningAddress(
|
|
63
|
+
ln: string,
|
|
64
|
+
opts?: { fetch: typeof globalThis.fetch },
|
|
65
|
+
): LNURL {
|
|
66
|
+
if (!z.string().email().safeParse(ln).success) {
|
|
67
|
+
throw new Error(
|
|
68
|
+
'Expected a lightning address in email-like format (eg "example@getalby.com")',
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const [name, host] = ln.split("@");
|
|
73
|
+
const url = new URL(`/.well-known/lnurlp/${name}`, `https://${host}`);
|
|
74
|
+
|
|
75
|
+
return new LNURL(url, opts);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Returns the LNURL object as a bech32-encoded `lnurl1...` string. */
|
|
79
|
+
toString(): `lnurl1${string}` {
|
|
80
|
+
const data = new TextEncoder().encode(this.url.toString());
|
|
81
|
+
const words = bech32.toWords(data);
|
|
82
|
+
return bech32.encode("lnurl", words, 20000);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Resolve an LNURL to its details. */
|
|
86
|
+
async getDetails(opts?: { signal?: AbortSignal }): Promise<LNURLDetails> {
|
|
87
|
+
const response = await this.fetch(this.url, opts);
|
|
88
|
+
const json = await response.json();
|
|
89
|
+
return LNURL.lnurlDetailsSchema().parse(json);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Generate an LNURL invoice from the params. */
|
|
93
|
+
async getInvoice(opts: {
|
|
94
|
+
/** Amount in millisatoshis to send to the user. */
|
|
95
|
+
amount: number;
|
|
96
|
+
/** NIP-57 Zap Request (kind 9734) event. */
|
|
97
|
+
nostr?: NostrEvent;
|
|
98
|
+
/** Signal to abort the request. */
|
|
99
|
+
signal?: AbortSignal;
|
|
100
|
+
}): Promise<LNURLCallback> {
|
|
101
|
+
const details = await this.getDetails(opts);
|
|
102
|
+
const callback = new URL(details.callback);
|
|
103
|
+
|
|
104
|
+
callback.searchParams.set("amount", opts.amount.toString());
|
|
105
|
+
callback.searchParams.set("lnurl", this.toString());
|
|
106
|
+
|
|
107
|
+
if (opts.nostr) {
|
|
108
|
+
callback.searchParams.set("nostr", JSON.stringify(opts.nostr));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const response = await this.fetch(callback, opts);
|
|
112
|
+
const json = await response.json();
|
|
113
|
+
|
|
114
|
+
return LNURL.lnurlCallbackSchema().parse(json);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** LNURL response schema. */
|
|
118
|
+
static lnurlDetailsSchema(): z.ZodType<LNURLDetails> {
|
|
119
|
+
return z.object({
|
|
120
|
+
allowsNostr: z.boolean().optional(),
|
|
121
|
+
callback: z.string().url(),
|
|
122
|
+
commentAllowed: z.number().nonnegative().int().optional(),
|
|
123
|
+
maxSendable: z.number().positive().int(),
|
|
124
|
+
minSendable: z.number().positive().int(),
|
|
125
|
+
metadata: z.string(),
|
|
126
|
+
nostrPubkey: n.id().optional(),
|
|
127
|
+
tag: z.literal("payRequest"),
|
|
128
|
+
}).superRefine((details, ctx) => {
|
|
129
|
+
if (details.minSendable > details.maxSendable) {
|
|
130
|
+
ctx.addIssue({
|
|
131
|
+
code: z.ZodIssueCode.custom,
|
|
132
|
+
message: "minSendable must be less than or equal to maxSendable",
|
|
133
|
+
path: ["minSendable"],
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}) as z.ZodType<LNURLDetails>;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** LNURL callback schema. */
|
|
140
|
+
static lnurlCallbackSchema(): z.ZodType<LNURLCallback> {
|
|
141
|
+
return z.object({
|
|
142
|
+
pr: n.bech32("lnbc"),
|
|
143
|
+
routes: z.tuple([]),
|
|
144
|
+
}) as unknown as z.ZodType<LNURLCallback>;
|
|
145
|
+
}
|
|
146
|
+
}
|
package/ln/mod.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** LNURL `payRequest` details, as defined by LUD-06. Includes additional properties from NIP-57. */
|
|
2
|
+
export interface LNURLDetails {
|
|
3
|
+
/** Whether the LN SERVICE supports NIP-57 Lightning Zaps. */
|
|
4
|
+
allowsNostr?: boolean;
|
|
5
|
+
/** The URL from LN SERVICE which will accept the pay request parameters. */
|
|
6
|
+
callback: string;
|
|
7
|
+
/** The number of characters accepted for the `comment` query parameter on subsequent callback. (Should be interpreted as 0 if not provided). */
|
|
8
|
+
commentAllowed?: number;
|
|
9
|
+
/** Max millisatoshi amount LN SERVICE is willing to receive. */
|
|
10
|
+
maxSendable: number;
|
|
11
|
+
/** Min millisatoshi amount LN SERVICE is willing to receive, can not be less than 1 or more than `maxSendable`. */
|
|
12
|
+
minSendable: number;
|
|
13
|
+
/** Metadata json which must be presented as raw string here, this is required to pass signature verification at a later step. */
|
|
14
|
+
metadata: string;
|
|
15
|
+
/** The Nostr pubkey LN SERVICE will use to sign zap receipt events. Clients will use this to validate zap receipts. */
|
|
16
|
+
nostrPubkey?: string;
|
|
17
|
+
/** Type of LNURL. */
|
|
18
|
+
tag: 'payRequest';
|
|
19
|
+
}
|
package/mod.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { BunkerURI } from './BunkerURI';
|
|
2
|
+
export { NBrowserSigner } from './NBrowserSigner';
|
|
3
|
+
export { NCache } from './NCache';
|
|
4
|
+
export { NConnectSigner, type NConnectSignerOpts } from './NConnectSigner';
|
|
5
|
+
export { NIP05 } from './NIP05';
|
|
6
|
+
export { NIP50 } from './NIP50';
|
|
7
|
+
export { NIP98 } from './NIP98';
|
|
8
|
+
export { NKinds } from './NKinds';
|
|
9
|
+
export { NPool, type NPoolOpts } from './NPool';
|
|
10
|
+
export { NRelay1, type NRelay1Opts } from './NRelay1';
|
|
11
|
+
export { NSchema } from './NSchema';
|
|
12
|
+
export { NSecSigner } from './NSecSigner';
|
|
13
|
+
export { NSet } from './NSet';
|
|
14
|
+
export { RelayError } from './RelayError';
|
|
15
|
+
|
|
16
|
+
export type * from '@nostrify/types';
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nostrify/nostrify",
|
|
3
|
+
"version": "0.46.4",
|
|
4
|
+
"exports": {
|
|
5
|
+
".": "./mod.ts",
|
|
6
|
+
"./ln": "./ln/mod.ts",
|
|
7
|
+
"./test": "./test/mod.ts",
|
|
8
|
+
"./uploaders": "./uploaders/mod.ts",
|
|
9
|
+
"./utils": "./utils/mod.ts"
|
|
10
|
+
},
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"types": "dist/index.d.ts",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"ws": "^8.18.3",
|
|
15
|
+
"@nostrify/types": "0.36.0"
|
|
16
|
+
},
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc -p tsconfig.json"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { genEvent } from '@nostrify/nostrify/test';
|
|
2
|
+
import { assertRejects } from '@std/assert';
|
|
3
|
+
|
|
4
|
+
import { ErrorRelay } from './ErrorRelay.ts';
|
|
5
|
+
|
|
6
|
+
Deno.test('ErrorRelay', async () => {
|
|
7
|
+
const store = new ErrorRelay();
|
|
8
|
+
await assertRejects(() => store.event(genEvent()));
|
|
9
|
+
await assertRejects(() => store.query([]));
|
|
10
|
+
await assertRejects(() => store.count([]));
|
|
11
|
+
await assertRejects(() => store.remove([]));
|
|
12
|
+
await assertRejects(() => store.close());
|
|
13
|
+
|
|
14
|
+
await assertRejects(async () => {
|
|
15
|
+
for await (const _ of store.req([])) {
|
|
16
|
+
// Do nothing.
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// deno-lint-ignore-file require-await require-yield
|
|
2
|
+
import {
|
|
3
|
+
NostrEvent,
|
|
4
|
+
NostrFilter,
|
|
5
|
+
NostrRelayCLOSED,
|
|
6
|
+
NostrRelayCOUNT,
|
|
7
|
+
NostrRelayEOSE,
|
|
8
|
+
NostrRelayEVENT,
|
|
9
|
+
NRelay,
|
|
10
|
+
} from '@nostrify/types';
|
|
11
|
+
|
|
12
|
+
/** A relay storage class that intentionally throws errors for every method. */
|
|
13
|
+
export class ErrorRelay implements NRelay {
|
|
14
|
+
async *req(
|
|
15
|
+
_filters: NostrFilter[],
|
|
16
|
+
_opts?: { signal?: AbortSignal },
|
|
17
|
+
): AsyncIterable<NostrRelayEVENT | NostrRelayEOSE | NostrRelayCLOSED> {
|
|
18
|
+
throw new Error('This error is intentional.');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async event(_event: NostrEvent, _opts?: { signal?: AbortSignal }): Promise<void> {
|
|
22
|
+
throw new Error('This error is intentional.');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async query(_filters: NostrFilter[], _opts?: { signal?: AbortSignal }): Promise<NostrEvent[]> {
|
|
26
|
+
throw new Error('This error is intentional.');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async count(_filters: NostrFilter[], _opts?: { signal?: AbortSignal }): Promise<NostrRelayCOUNT[2]> {
|
|
30
|
+
throw new Error('This error is intentional.');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async remove(_filters: NostrFilter[], _opts?: { signal?: AbortSignal }): Promise<void> {
|
|
34
|
+
throw new Error('This error is intentional.');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async close(): Promise<void> {
|
|
38
|
+
throw new Error('This error is intentional.');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { assertEquals } from '@std/assert';
|
|
2
|
+
|
|
3
|
+
import { MockRelay } from './MockRelay.ts';
|
|
4
|
+
|
|
5
|
+
import event1 from '../../../fixtures/event-1.json' with { type: 'json' };
|
|
6
|
+
|
|
7
|
+
Deno.test('MockRelay', async () => {
|
|
8
|
+
const relay = new MockRelay();
|
|
9
|
+
|
|
10
|
+
assertEquals(await relay.count([{ ids: [event1.id] }]), { count: 0, approximate: false });
|
|
11
|
+
|
|
12
|
+
await relay.event(event1);
|
|
13
|
+
|
|
14
|
+
assertEquals(await relay.count([{ ids: [event1.id] }]), { count: 1, approximate: false });
|
|
15
|
+
|
|
16
|
+
const result = await relay.query([{ ids: [event1.id] }]);
|
|
17
|
+
assertEquals(result[0], event1);
|
|
18
|
+
|
|
19
|
+
assertEquals(relay.subs.size, 0); // cleanup
|
|
20
|
+
});
|