applesauce-core 0.0.0-next-20250308144838 → 0.0.0-next-20250309231023

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.
@@ -0,0 +1,4 @@
1
+ import { NostrEvent } from "nostr-tools";
2
+ import { HiddenContentSigner } from "./hidden-content.js";
3
+ /** Returns the decrypted content of a direct message */
4
+ export declare function decryptDirectMessage(message: NostrEvent, signer: HiddenContentSigner): Promise<string>;
@@ -0,0 +1,5 @@
1
+ import { getHiddenContent, unlockHiddenContent } from "./hidden-content.js";
2
+ /** Returns the decrypted content of a direct message */
3
+ export async function decryptDirectMessage(message, signer) {
4
+ return getHiddenContent(message) || (await unlockHiddenContent(message, signer));
5
+ }
@@ -0,0 +1,12 @@
1
+ import { NostrEvent, UnsignedEvent } from "nostr-tools";
2
+ import { HiddenContentSigner } from "./hidden-content.js";
3
+ export declare const GiftWrapSealSymbol: unique symbol;
4
+ export declare const GiftWrapEventSymbol: unique symbol;
5
+ /** Returns the unsigned seal event in a gift-wrap event */
6
+ export declare function getGiftWrapSeal(gift: NostrEvent): NostrEvent;
7
+ /** Returns the unsigned event in the gift-wrap seal */
8
+ export declare function getGiftWrapEvent(gift: NostrEvent): UnsignedEvent;
9
+ /** Returns if a gift-wrap event or gift-wrap seal is locked */
10
+ export declare function isGiftWrapLocked(gift: NostrEvent): boolean;
11
+ /** Unlocks and returns the unsigned seal event in a gift-wrap */
12
+ export declare function unlockGiftWrap(gift: NostrEvent, signer: HiddenContentSigner): Promise<UnsignedEvent>;
@@ -0,0 +1,43 @@
1
+ import { verifyEvent } from "nostr-tools";
2
+ import { getHiddenContent, isHiddenContentLocked, unlockHiddenContent } from "./hidden-content.js";
3
+ import { getOrComputeCachedValue } from "./cache.js";
4
+ export const GiftWrapSealSymbol = Symbol.for("gift-wrap-seal");
5
+ export const GiftWrapEventSymbol = Symbol.for("gift-wrap-event");
6
+ /** Returns the unsigned seal event in a gift-wrap event */
7
+ export function getGiftWrapSeal(gift) {
8
+ return getOrComputeCachedValue(gift, GiftWrapSealSymbol, () => {
9
+ const plaintext = getHiddenContent(gift);
10
+ if (!plaintext)
11
+ throw new Error("Gift-wrap is locked");
12
+ const seal = JSON.parse(plaintext);
13
+ // verify the seal is valid
14
+ verifyEvent(seal);
15
+ return seal;
16
+ });
17
+ }
18
+ /** Returns the unsigned event in the gift-wrap seal */
19
+ export function getGiftWrapEvent(gift) {
20
+ return getOrComputeCachedValue(gift, GiftWrapEventSymbol, () => {
21
+ const seal = getGiftWrapSeal(gift);
22
+ const plaintext = getHiddenContent(seal);
23
+ if (!plaintext)
24
+ throw new Error("Gift-wrap seal is locked");
25
+ const event = JSON.parse(plaintext);
26
+ if (event.pubkey !== seal.pubkey)
27
+ throw new Error("Seal author does not match content");
28
+ return event;
29
+ });
30
+ }
31
+ /** Returns if a gift-wrap event or gift-wrap seal is locked */
32
+ export function isGiftWrapLocked(gift) {
33
+ return isHiddenContentLocked(gift) || isHiddenContentLocked(getGiftWrapSeal(gift));
34
+ }
35
+ /** Unlocks and returns the unsigned seal event in a gift-wrap */
36
+ export async function unlockGiftWrap(gift, signer) {
37
+ if (isHiddenContentLocked(gift))
38
+ await unlockHiddenContent(gift, signer);
39
+ const seal = getGiftWrapSeal(gift);
40
+ if (isHiddenContentLocked(seal))
41
+ await unlockHiddenContent(seal, signer);
42
+ return getGiftWrapEvent(gift);
43
+ }
@@ -0,0 +1,44 @@
1
+ import { UnsignedEvent, type EventTemplate, type NostrEvent } from "nostr-tools";
2
+ export declare const HiddenContentSymbol: unique symbol;
3
+ export type HiddenContentSigner = {
4
+ nip04?: {
5
+ encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
6
+ decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
7
+ };
8
+ nip44?: {
9
+ encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
10
+ decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
11
+ };
12
+ };
13
+ /** Various event kinds that can have encrypted tags in their content and which encryption method they use */
14
+ export declare const EventContentEncryptionMethod: Record<number, "nip04" | "nip44">;
15
+ /** Checks if an event can have hidden content */
16
+ export declare function canHaveHiddenContent(kind: number): boolean;
17
+ /** Checks if an event has hidden content */
18
+ export declare function hasHiddenContent(event: {
19
+ kind: number;
20
+ content: string;
21
+ }): boolean;
22
+ /** Returns the hidden tags for an event if they are unlocked */
23
+ export declare function getHiddenContent(event: NostrEvent | EventTemplate): string | undefined;
24
+ /** Checks if the hidden tags are locked */
25
+ export declare function isHiddenContentLocked(event: NostrEvent | UnsignedEvent): boolean;
26
+ /** Returns either nip04 or nip44 encryption methods depending on event kind */
27
+ export declare function getHiddenContentEncryptionMethods(kind: number, signer: HiddenContentSigner): {
28
+ encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
29
+ decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
30
+ } | {
31
+ encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
32
+ decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
33
+ };
34
+ /**
35
+ * Unlocks the encrypted content in an event
36
+ * @param event The event with content to decrypt
37
+ * @param signer A signer to use to decrypt the tags
38
+ * @throws
39
+ */
40
+ export declare function unlockHiddenContent(event: {
41
+ kind: number;
42
+ pubkey: string;
43
+ content: string;
44
+ }, signer: HiddenContentSigner): Promise<string>;
@@ -0,0 +1,66 @@
1
+ import * as kinds from "nostr-tools/kinds";
2
+ import { GROUPS_LIST_KIND } from "./groups.js";
3
+ export const HiddenContentSymbol = Symbol.for("hidden-content");
4
+ /** Various event kinds that can have encrypted tags in their content and which encryption method they use */
5
+ export const EventContentEncryptionMethod = {
6
+ // NIP-60 wallet
7
+ 17375: "nip44",
8
+ 7375: "nip44",
9
+ 7376: "nip44",
10
+ // DMs
11
+ [kinds.EncryptedDirectMessage]: "nip04",
12
+ // Gift wraps
13
+ [kinds.GiftWrap]: "nip44",
14
+ // NIP-51 lists
15
+ [kinds.BookmarkList]: "nip04",
16
+ [kinds.InterestsList]: "nip04",
17
+ [kinds.Mutelist]: "nip04",
18
+ [kinds.CommunitiesList]: "nip04",
19
+ [kinds.PublicChatsList]: "nip04",
20
+ [kinds.SearchRelaysList]: "nip04",
21
+ [GROUPS_LIST_KIND]: "nip04",
22
+ // NIP-51 sets
23
+ [kinds.Bookmarksets]: "nip04",
24
+ [kinds.Relaysets]: "nip04",
25
+ [kinds.Followsets]: "nip04",
26
+ [kinds.Curationsets]: "nip04",
27
+ [kinds.Interestsets]: "nip04",
28
+ };
29
+ /** Checks if an event can have hidden content */
30
+ export function canHaveHiddenContent(kind) {
31
+ return EventContentEncryptionMethod[kind] !== undefined;
32
+ }
33
+ /** Checks if an event has hidden content */
34
+ export function hasHiddenContent(event) {
35
+ return canHaveHiddenContent(event.kind) && event.content.length > 0;
36
+ }
37
+ /** Returns the hidden tags for an event if they are unlocked */
38
+ export function getHiddenContent(event) {
39
+ return Reflect.get(event, HiddenContentSymbol);
40
+ }
41
+ /** Checks if the hidden tags are locked */
42
+ export function isHiddenContentLocked(event) {
43
+ return hasHiddenContent(event) && getHiddenContent(event) === undefined;
44
+ }
45
+ /** Returns either nip04 or nip44 encryption methods depending on event kind */
46
+ export function getHiddenContentEncryptionMethods(kind, signer) {
47
+ const method = EventContentEncryptionMethod[kind];
48
+ const encryption = signer[method];
49
+ if (!encryption)
50
+ throw new Error(`Signer does not support ${method} encryption`);
51
+ return encryption;
52
+ }
53
+ /**
54
+ * Unlocks the encrypted content in an event
55
+ * @param event The event with content to decrypt
56
+ * @param signer A signer to use to decrypt the tags
57
+ * @throws
58
+ */
59
+ export async function unlockHiddenContent(event, signer) {
60
+ if (!canHaveHiddenContent(event.kind))
61
+ throw new Error("Event kind does not support hidden content");
62
+ const encryption = getHiddenContentEncryptionMethods(event.kind, signer);
63
+ const plaintext = await encryption.decrypt(event.pubkey, event.content);
64
+ Reflect.set(event, HiddenContentSymbol, plaintext);
65
+ return plaintext;
66
+ }
@@ -1,18 +1,7 @@
1
1
  import { EventTemplate, NostrEvent } from "nostr-tools";
2
2
  import { EventStore } from "../event-store/event-store.js";
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
- nip44?: {
9
- encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
10
- decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
11
- };
12
- };
3
+ import { HiddenContentSigner } from "./hidden-content.js";
13
4
  export declare const HiddenTagsSymbol: unique symbol;
14
- /** Various event kinds that can have encrypted tags in their content and which encryption method they use */
15
- export declare const EventEncryptionMethod: Record<number, "nip04" | "nip44">;
16
5
  /** Checks if an event can have hidden tags */
17
6
  export declare function canHaveHiddenTags(kind: number): boolean;
18
7
  /** Checks if an event has hidden tags */
@@ -22,7 +11,7 @@ export declare function getHiddenTags(event: NostrEvent | EventTemplate): string
22
11
  /** Checks if the hidden tags are locked */
23
12
  export declare function isHiddenTagsLocked(event: NostrEvent): boolean;
24
13
  /** Returns either nip04 or nip44 encryption method depending on list kind */
25
- export declare function getListEncryptionMethods(kind: number, signer: HiddenTagsSigner): {
14
+ export declare function getListEncryptionMethods(kind: number, signer: HiddenContentSigner): {
26
15
  encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
27
16
  decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
28
17
  } | {
@@ -40,9 +29,10 @@ export declare function unlockHiddenTags<T extends {
40
29
  kind: number;
41
30
  pubkey: string;
42
31
  content: string;
43
- }>(event: T, signer: HiddenTagsSigner, store?: EventStore): Promise<T>;
32
+ }>(event: T, signer: HiddenContentSigner, store?: EventStore): Promise<string[][]>;
44
33
  /**
45
34
  * Override the hidden tags in an event
35
+ * @deprecated use EventFactory to create draft events
46
36
  * @throws
47
37
  */
48
- export declare function overrideHiddenTags(event: NostrEvent, hidden: string[][], signer: HiddenTagsSigner): Promise<EventTemplate>;
38
+ export declare function overrideHiddenTags(event: NostrEvent, hidden: string[][], signer: HiddenContentSigner): Promise<EventTemplate>;
@@ -1,30 +1,10 @@
1
- import { kinds } from "nostr-tools";
2
- import { GROUPS_LIST_KIND } from "./groups.js";
3
1
  import { unixNow } from "./time.js";
4
2
  import { isEvent } from "./event.js";
3
+ import { canHaveHiddenContent, getHiddenContentEncryptionMethods, unlockHiddenContent, } from "./hidden-content.js";
5
4
  export const HiddenTagsSymbol = Symbol.for("hidden-tags");
6
- /** Various event kinds that can have encrypted tags in their content and which encryption method they use */
7
- export const EventEncryptionMethod = {
8
- // NIP-60 wallet
9
- 17375: "nip44",
10
- // NIP-51 lists
11
- [kinds.BookmarkList]: "nip04",
12
- [kinds.InterestsList]: "nip04",
13
- [kinds.Mutelist]: "nip04",
14
- [kinds.CommunitiesList]: "nip04",
15
- [kinds.PublicChatsList]: "nip04",
16
- [kinds.SearchRelaysList]: "nip04",
17
- [GROUPS_LIST_KIND]: "nip04",
18
- // NIP-51 sets
19
- [kinds.Bookmarksets]: "nip04",
20
- [kinds.Relaysets]: "nip04",
21
- [kinds.Followsets]: "nip04",
22
- [kinds.Curationsets]: "nip04",
23
- [kinds.Interestsets]: "nip04",
24
- };
25
5
  /** Checks if an event can have hidden tags */
26
6
  export function canHaveHiddenTags(kind) {
27
- return EventEncryptionMethod[kind] !== undefined;
7
+ return canHaveHiddenContent(kind);
28
8
  }
29
9
  /** Checks if an event has hidden tags */
30
10
  export function hasHiddenTags(event) {
@@ -40,11 +20,7 @@ export function isHiddenTagsLocked(event) {
40
20
  }
41
21
  /** Returns either nip04 or nip44 encryption method depending on list kind */
42
22
  export function getListEncryptionMethods(kind, signer) {
43
- const method = EventEncryptionMethod[kind];
44
- const encryption = signer[method];
45
- if (!encryption)
46
- throw new Error(`Signer does not support ${method} encryption`);
47
- return encryption;
23
+ return getHiddenContentEncryptionMethods(kind, signer);
48
24
  }
49
25
  /**
50
26
  * Decrypts the private list
@@ -56,8 +32,7 @@ export function getListEncryptionMethods(kind, signer) {
56
32
  export async function unlockHiddenTags(event, signer, store) {
57
33
  if (!canHaveHiddenTags(event.kind))
58
34
  throw new Error("Event kind does not support hidden tags");
59
- const encryption = getListEncryptionMethods(event.kind, signer);
60
- const plaintext = await encryption.decrypt(event.pubkey, event.content);
35
+ const plaintext = await unlockHiddenContent(event, signer);
61
36
  const parsed = JSON.parse(plaintext);
62
37
  if (!Array.isArray(parsed))
63
38
  throw new Error("Content is not an array of tags");
@@ -66,10 +41,11 @@ export async function unlockHiddenTags(event, signer, store) {
66
41
  Reflect.set(event, HiddenTagsSymbol, tags);
67
42
  if (store && isEvent(event))
68
43
  store.update(event);
69
- return event;
44
+ return tags;
70
45
  }
71
46
  /**
72
47
  * Override the hidden tags in an event
48
+ * @deprecated use EventFactory to create draft events
73
49
  * @throws
74
50
  */
75
51
  export async function overrideHiddenTags(event, hidden, signer) {
@@ -7,14 +7,17 @@ export * from "./comment.js";
7
7
  export * from "./contacts.js";
8
8
  export * from "./content.js";
9
9
  export * from "./delete.js";
10
+ export * from "./direct-messages.js";
10
11
  export * from "./dns-identity.js";
11
12
  export * from "./emoji.js";
12
13
  export * from "./event.js";
13
14
  export * from "./external-id.js";
14
15
  export * from "./file-metadata.js";
15
16
  export * from "./filter.js";
17
+ export * from "./gift-wraps.js";
16
18
  export * from "./groups.js";
17
19
  export * from "./hashtag.js";
20
+ export * from "./hidden-content.js";
18
21
  export * from "./hidden-tags.js";
19
22
  export * from "./json.js";
20
23
  export * from "./lists.js";
@@ -7,14 +7,17 @@ export * from "./comment.js";
7
7
  export * from "./contacts.js";
8
8
  export * from "./content.js";
9
9
  export * from "./delete.js";
10
+ export * from "./direct-messages.js";
10
11
  export * from "./dns-identity.js";
11
12
  export * from "./emoji.js";
12
13
  export * from "./event.js";
13
14
  export * from "./external-id.js";
14
15
  export * from "./file-metadata.js";
15
16
  export * from "./filter.js";
17
+ export * from "./gift-wraps.js";
16
18
  export * from "./groups.js";
17
19
  export * from "./hashtag.js";
20
+ export * from "./hidden-content.js";
18
21
  export * from "./hidden-tags.js";
19
22
  export * from "./json.js";
20
23
  export * from "./lists.js";
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "applesauce-core",
3
- "version": "0.0.0-next-20250308144838",
3
+ "version": "0.0.0-next-20250309231023",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "keywords": [
9
- "nostr"
9
+ "nostr",
10
+ "applesauce"
10
11
  ],
11
12
  "author": "hzrd149",
12
13
  "license": "MIT",
13
14
  "files": [
14
- "dist",
15
- "applesauce"
15
+ "dist"
16
16
  ],
17
17
  "exports": {
18
18
  ".": {