applesauce-core 0.0.0-next-20241119142128 → 0.0.0-next-20241119173145
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/helpers/event.d.ts +4 -1
- package/dist/helpers/event.js +9 -1
- package/dist/helpers/hidden-tags.d.ts +39 -0
- package/dist/helpers/hidden-tags.js +90 -0
- package/dist/helpers/hidden-tags.test.d.ts +1 -0
- package/dist/helpers/hidden-tags.test.js +27 -0
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.js +1 -0
- package/package.json +1 -1
package/dist/helpers/event.d.ts
CHANGED
|
@@ -24,7 +24,10 @@ export declare function getEventUID(event: NostrEvent): string;
|
|
|
24
24
|
export declare function getReplaceableUID(kind: number, pubkey: string, d?: string): string;
|
|
25
25
|
/** Returns a Set of tag names and values that are indexable */
|
|
26
26
|
export declare function getIndexableTags(event: NostrEvent): Set<string>;
|
|
27
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Returns the second index ( tag[1] ) of the first tag that matches the name
|
|
29
|
+
* If the event has any hidden tags they will be searched first
|
|
30
|
+
*/
|
|
28
31
|
export declare function getTagValue(event: NostrEvent, name: string): string | undefined;
|
|
29
32
|
/** Sets events verified flag without checking anything */
|
|
30
33
|
export declare function fakeVerifyEvent(event: NostrEvent): event is VerifiedEvent;
|
package/dist/helpers/event.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { kinds, verifiedSymbol } from "nostr-tools";
|
|
2
2
|
import { INDEXABLE_TAGS } from "../event-store/common.js";
|
|
3
|
+
import { getHiddenTags } from "./hidden-tags.js";
|
|
3
4
|
export const EventUIDSymbol = Symbol.for("event-uid");
|
|
4
5
|
export const EventIndexableTagsSymbol = Symbol.for("indexable-tags");
|
|
5
6
|
export const FromCacheSymbol = Symbol.for("from-cache");
|
|
@@ -46,8 +47,15 @@ export function getIndexableTags(event) {
|
|
|
46
47
|
}
|
|
47
48
|
return indexable;
|
|
48
49
|
}
|
|
49
|
-
/**
|
|
50
|
+
/**
|
|
51
|
+
* Returns the second index ( tag[1] ) of the first tag that matches the name
|
|
52
|
+
* If the event has any hidden tags they will be searched first
|
|
53
|
+
*/
|
|
50
54
|
export function getTagValue(event, name) {
|
|
55
|
+
const hidden = getHiddenTags(event);
|
|
56
|
+
const hiddenValue = hidden?.find((t) => t[0] === name)?.[1];
|
|
57
|
+
if (hiddenValue)
|
|
58
|
+
return hiddenValue;
|
|
51
59
|
return event.tags.find((t) => t[0] === name)?.[1];
|
|
52
60
|
}
|
|
53
61
|
/** Sets events verified flag without checking anything */
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { EventTemplate, NostrEvent, UnsignedEvent } from "nostr-tools";
|
|
2
|
+
import { EventStore } from "applesauce-core";
|
|
3
|
+
export type HiddenTagsSigner = {
|
|
4
|
+
nip04: {
|
|
5
|
+
encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
|
|
6
|
+
decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
export type TagOperation = (tags: string[][]) => string[][];
|
|
10
|
+
export declare const HiddenTagsSymbol: unique symbol;
|
|
11
|
+
export declare const EventsWithHiddenTags: number[];
|
|
12
|
+
/** Checks if an event can have hidden tags */
|
|
13
|
+
export declare function canHaveHiddenTags(event: NostrEvent | EventTemplate): boolean;
|
|
14
|
+
/** Checks if an event has hidden tags */
|
|
15
|
+
export declare function hasHiddenTags(event: NostrEvent | EventTemplate): boolean;
|
|
16
|
+
/** Returns the hidden tags from an event if they are unlocked */
|
|
17
|
+
export declare function getHiddenTags(event: NostrEvent | EventTemplate): string[][] | undefined;
|
|
18
|
+
export declare function isHiddenTagsLocked(event: NostrEvent): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Decrypts the private list
|
|
21
|
+
* @param event The list event to decrypt
|
|
22
|
+
* @param signer A signer to use to decrypt the tags
|
|
23
|
+
* @param store An optional EventStore to notify about the update
|
|
24
|
+
*/
|
|
25
|
+
export declare function unlockHiddenTags(event: NostrEvent, signer: HiddenTagsSigner, store?: EventStore): Promise<NostrEvent>;
|
|
26
|
+
/**
|
|
27
|
+
* Modifies tags and returns an EventTemplate
|
|
28
|
+
* @param event Event to modify
|
|
29
|
+
* @param operations Operations for hidden and public tags
|
|
30
|
+
* @param signer A signer to use to decrypt the tags
|
|
31
|
+
*/
|
|
32
|
+
export declare function modifyEventTags(event: NostrEvent | UnsignedEvent, operations: {
|
|
33
|
+
public?: TagOperation;
|
|
34
|
+
hidden?: TagOperation;
|
|
35
|
+
}, signer?: HiddenTagsSigner): Promise<EventTemplate>;
|
|
36
|
+
/**
|
|
37
|
+
* Override the hidden tags in an event
|
|
38
|
+
*/
|
|
39
|
+
export declare function overrideHiddenTags(event: NostrEvent, hidden: string[][], signer: HiddenTagsSigner): Promise<EventTemplate>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { unixNow } from "applesauce-core/helpers";
|
|
2
|
+
import { kinds } from "nostr-tools";
|
|
3
|
+
export const HiddenTagsSymbol = Symbol.for("hidden-tags");
|
|
4
|
+
export const EventsWithHiddenTags = [
|
|
5
|
+
37375, // NIP-60 wallet
|
|
6
|
+
// NIP-51 lists
|
|
7
|
+
kinds.BookmarkList,
|
|
8
|
+
kinds.InterestsList,
|
|
9
|
+
kinds.Mutelist,
|
|
10
|
+
kinds.CommunitiesList,
|
|
11
|
+
kinds.PublicChatsList,
|
|
12
|
+
kinds.SearchRelaysList,
|
|
13
|
+
kinds.SearchRelaysList,
|
|
14
|
+
10009, // NIP-29 groups
|
|
15
|
+
// NIP-51 sets
|
|
16
|
+
kinds.Bookmarksets,
|
|
17
|
+
kinds.Relaysets,
|
|
18
|
+
kinds.Followsets,
|
|
19
|
+
kinds.Curationsets,
|
|
20
|
+
kinds.Interestsets,
|
|
21
|
+
];
|
|
22
|
+
/** Checks if an event can have hidden tags */
|
|
23
|
+
export function canHaveHiddenTags(event) {
|
|
24
|
+
return EventsWithHiddenTags.includes(event.kind);
|
|
25
|
+
}
|
|
26
|
+
/** Checks if an event has hidden tags */
|
|
27
|
+
export function hasHiddenTags(event) {
|
|
28
|
+
return canHaveHiddenTags(event) && event.content.length > 0;
|
|
29
|
+
}
|
|
30
|
+
/** Returns the hidden tags from an event if they are unlocked */
|
|
31
|
+
export function getHiddenTags(event) {
|
|
32
|
+
return Reflect.get(event, HiddenTagsSymbol);
|
|
33
|
+
}
|
|
34
|
+
export function isHiddenTagsLocked(event) {
|
|
35
|
+
return hasHiddenTags(event) && getHiddenTags(event) === undefined;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Decrypts the private list
|
|
39
|
+
* @param event The list event to decrypt
|
|
40
|
+
* @param signer A signer to use to decrypt the tags
|
|
41
|
+
* @param store An optional EventStore to notify about the update
|
|
42
|
+
*/
|
|
43
|
+
export async function unlockHiddenTags(event, signer, store) {
|
|
44
|
+
const plaintext = await signer.nip04.decrypt(event.pubkey, event.content);
|
|
45
|
+
const parsed = JSON.parse(plaintext);
|
|
46
|
+
if (!Array.isArray(parsed))
|
|
47
|
+
throw new Error("Content is not an array of tags");
|
|
48
|
+
// Convert array to tags array string[][]
|
|
49
|
+
const tags = parsed.filter((t) => Array.isArray(t)).map((t) => t.map((v) => String(v)));
|
|
50
|
+
Reflect.set(event, HiddenTagsSymbol, tags);
|
|
51
|
+
if (store)
|
|
52
|
+
store.update(event);
|
|
53
|
+
return event;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Modifies tags and returns an EventTemplate
|
|
57
|
+
* @param event Event to modify
|
|
58
|
+
* @param operations Operations for hidden and public tags
|
|
59
|
+
* @param signer A signer to use to decrypt the tags
|
|
60
|
+
*/
|
|
61
|
+
export async function modifyEventTags(event, operations, signer) {
|
|
62
|
+
const draft = { content: event.content, tags: event.tags, kind: event.kind, created_at: unixNow() };
|
|
63
|
+
if (operations.public) {
|
|
64
|
+
draft.tags = operations.public(event.tags);
|
|
65
|
+
}
|
|
66
|
+
if (operations.hidden) {
|
|
67
|
+
if (!signer)
|
|
68
|
+
throw new Error("Missing signer for hidden tags");
|
|
69
|
+
if (!canHaveHiddenTags(event))
|
|
70
|
+
throw new Error("Event can not have hidden tags");
|
|
71
|
+
const hidden = hasHiddenTags(event) ? getHiddenTags(event) : [];
|
|
72
|
+
if (!hidden)
|
|
73
|
+
throw new Error("Hidden tags are locked");
|
|
74
|
+
const newHidden = operations.hidden(hidden);
|
|
75
|
+
draft.content = await signer.nip04.encrypt(event.pubkey, JSON.stringify(newHidden));
|
|
76
|
+
}
|
|
77
|
+
return draft;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Override the hidden tags in an event
|
|
81
|
+
*/
|
|
82
|
+
export async function overrideHiddenTags(event, hidden, signer) {
|
|
83
|
+
const ciphertext = await signer.nip04.encrypt(event.pubkey, JSON.stringify(hidden));
|
|
84
|
+
return {
|
|
85
|
+
kind: event.kind,
|
|
86
|
+
content: ciphertext,
|
|
87
|
+
created_at: unixNow(),
|
|
88
|
+
tags: event.tags,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getHiddenTags, unixNow, unlockHiddenTags } from "applesauce-core/helpers";
|
|
2
|
+
import { finalizeEvent, generateSecretKey, getPublicKey, kinds, nip04 } from "nostr-tools";
|
|
3
|
+
const key = generateSecretKey();
|
|
4
|
+
const pubkey = getPublicKey(key);
|
|
5
|
+
const signer = {
|
|
6
|
+
nip04: {
|
|
7
|
+
encrypt: (pubkey, plaintext) => nip04.encrypt(key, pubkey, plaintext),
|
|
8
|
+
decrypt: (pubkey, ciphertext) => nip04.decrypt(key, pubkey, ciphertext),
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
describe("Private Lists", () => {
|
|
12
|
+
describe("unlockHiddenTags", () => {
|
|
13
|
+
let list;
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
list = finalizeEvent({
|
|
16
|
+
kind: kinds.Mutelist,
|
|
17
|
+
created_at: unixNow(),
|
|
18
|
+
content: await nip04.encrypt(key, pubkey, JSON.stringify([["p", "npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr"]])),
|
|
19
|
+
tags: [],
|
|
20
|
+
}, key);
|
|
21
|
+
});
|
|
22
|
+
it("should unlock hidden tags", async () => {
|
|
23
|
+
await unlockHiddenTags(list, signer);
|
|
24
|
+
expect(getHiddenTags(list)).toEqual(expect.arrayContaining([["p", "npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr"]]));
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
});
|
package/dist/helpers/index.d.ts
CHANGED
package/dist/helpers/index.js
CHANGED