@@ -7,15 +7,17 @@ import { NDKUser } from "../user";
77import { NDKRelaySet } from "../relay/sets" ;
88import { NDKPrivateKeySigner } from "../signers/private-key" ;
99import { NIP73EntityType } from "./nip73" ;
10+ import { NDKSigner } from "../signers" ;
11+ import { NDKKind } from "./kinds" ;
12+
13+ const ndk = new NDK ( ) ;
1014
1115describe ( "NDKEvent" , ( ) => {
12- let ndk : NDK ;
1316 let event : NDKEvent ;
1417 let user1 : NDKUser ;
1518 let user2 : NDKUser ;
1619
1720 beforeEach ( ( ) => {
18- ndk = new NDK ( ) ;
1921 user1 = new NDKUser ( {
2022 npub : "npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft" ,
2123 } ) ;
@@ -433,4 +435,133 @@ describe("NDKEvent", () => {
433435 } ) . toThrow ( "Unsupported NIP-73 entity type: unsupported" ) ;
434436 } ) ;
435437 } ) ;
438+
439+ fdescribe ( "reply" , ( ) => {
440+ const signers = [ 0 , 1 , 2 ] . map ( i => NDKPrivateKeySigner . generate ( ) ) ;
441+ let users : NDKUser [ ] ;
442+
443+ beforeEach ( async ( ) => {
444+ users = await Promise . all ( signers . map ( s => s . user ( ) ) ) ;
445+ } ) ;
446+
447+ const sign = async ( event : Partial < NostrEvent > , signer = signers [ 0 ] ) => {
448+ const e = new NDKEvent ( ndk , event as NostrEvent ) ;
449+ await e . sign ( signer ) ;
450+ return e ;
451+ } ;
452+
453+ const reply = async ( event : NDKEvent , signer : NDKSigner ) => {
454+ const reply = event . reply ( ) ;
455+ await reply . sign ( signer ) ;
456+ return reply ;
457+ }
458+
459+ describe ( "replies to kind:1 events" , ( ) => {
460+ it ( "creates a reply using a kind 1 event" , async ( ) => {
461+ const op = await sign ( { kind : 1 } ) ;
462+ const reply = op . reply ( ) ;
463+ expect ( reply . kind ) . toBe ( 1 ) ;
464+ } ) ;
465+
466+ it ( 'carries over the root event of the OP' , async ( ) => {
467+ const root = await sign ( { kind : 1 } ) ;
468+ const reply1 = await reply ( root , signers [ 1 ] ) ;
469+ const reply2 = reply1 . reply ( ) ;
470+
471+ expect ( reply2 . tags ) . toContainEqual ( [ 'e' , root . id , '' , 'root' , root . pubkey ] ) ;
472+ expect ( reply2 . tags ) . toContainEqual ( [ 'p' , root . pubkey ] ) ;
473+ } ) ;
474+
475+ it ( 'adds a root marker for root events' , async ( ) => {
476+ const op = await sign ( { kind : 1 } ) ;
477+ const reply = op . reply ( ) ;
478+ expect ( reply . tags ) . toContainEqual ( [ 'e' , op . id , '' , 'root' , op . pubkey ] ) ;
479+ expect ( reply . tags ) . toContainEqual ( [ 'p' , op . pubkey ] ) ;
480+ } ) ;
481+
482+ it ( 'adds a reply marker for non-root events' , async ( ) => {
483+ const op = await sign ( { kind : 1 } ) ;
484+ const reply1 = await reply ( op , signers [ 1 ] ) ;
485+ const reply2 = reply1 . reply ( ) ;
486+ expect ( reply2 . tags ) . toContainEqual ( [ 'e' , reply1 . id , '' , 'reply' , reply1 . pubkey ] ) ;
487+ expect ( reply2 . tags ) . toContainEqual ( [ 'p' , reply1 . pubkey ] ) ;
488+ } ) ;
489+ } ) ;
490+
491+ describe ( "replies to other kinds" , ( ) => {
492+ let root : NDKEvent ;
493+ beforeAll ( async ( ) => {
494+ root = await sign ( { kind : 30023 } ) ;
495+ } ) ;
496+
497+ it ( "creates a reply using a kind 1111 event" , async ( ) => {
498+ const reply1 = await reply ( root , signers [ 1 ] ) ;
499+ expect ( reply1 . kind ) . toBe ( NDKKind . GenericReply ) ;
500+ } ) ;
501+
502+ it ( "tags the root event or scope using an appropriate uppercase tag (e.g., 'A', 'E', 'I')" , async ( ) => {
503+ const reply1 = await reply ( root , signers [ 1 ] ) ;
504+ expect ( reply1 . tags ) . toContainEqual ( [ 'A' , root . tagId ( ) , "" ] ) ;
505+ } ) ;
506+
507+ it ( "tags the root event with an 'a' for addressable events when it's a top level reply" , async ( ) => {
508+ const root = await sign ( { kind : 30023 } ) ;
509+ const reply1 = root . reply ( ) ;
510+ expect ( reply1 . tags ) . toContainEqual ( [ 'A' , root . tagId ( ) , "" ] ) ;
511+ expect ( reply1 . tags ) . toContainEqual ( [ 'a' , root . tagId ( ) , "" ] ) ;
512+ } ) ;
513+
514+ it ( "p-tags the author of the root event" , async ( ) => {
515+ const root = await sign ( { kind : 30023 } ) ;
516+ const reply1 = root . reply ( ) ;
517+ expect ( reply1 . tags ) . toContainEqual ( [ 'p' , root . pubkey ] ) ;
518+ } ) ;
519+
520+ it ( 'p-tags the author of the reply event' , async ( ) => {
521+ const root = await sign ( { kind : 30023 } ) ;
522+ const reply1 = await reply ( root , signers [ 1 ] ) ;
523+ const reply2 = reply1 . reply ( ) ;
524+ expect ( reply2 . tags ) . toContainEqual ( [ 'p' , reply1 . pubkey ] ) ;
525+ } ) ;
526+
527+ it ( "p-tags the author of the root event only once when it's the root reply" , async ( ) => {
528+ const root = await sign ( { kind : 30023 } ) ;
529+ const reply1 = root . reply ( ) ;
530+ expect ( reply1 . tags ) . toContainEqual ( [ 'p' , root . pubkey ] ) ;
531+ expect ( reply1 . tags . filter ( t => t [ 0 ] === 'p' ) ) . toHaveLength ( 1 ) ;
532+ } ) ;
533+
534+ it ( 'p-tags the author of the root and reply events' , async ( ) => {
535+ const reply1 = await reply ( root , signers [ 1 ] ) ;
536+ const reply2 = reply1 . reply ( ) ;
537+ expect ( reply2 . tags ) . toContainEqual ( [ 'p' , root . pubkey ] ) ;
538+ expect ( reply2 . tags ) . toContainEqual ( [ 'p' , reply1 . pubkey ] ) ;
539+ } ) ;
540+
541+ it ( "tags the root event or scope using an appropriate uppercase tag with the pubkey when it's an E tag" , async ( ) => {
542+ const root = await sign ( { kind : 20 } , signers [ 0 ] ) ;
543+ const reply1 = await reply ( root , signers [ 1 ] ) ;
544+ expect ( reply1 . tags ) . toContainEqual ( [ 'E' , root . tagId ( ) , "" , root . pubkey ] ) ;
545+ } ) ;
546+
547+ it ( "tags the parent item using an appropriate lowercase tag (e.g., 'a', 'e', 'i')" , async ( ) => {
548+ const reply1 = await reply ( root , signers [ 1 ] ) ;
549+ const reply2 = reply1 . reply ( ) ;
550+ expect ( reply2 . tags ) . toContainEqual ( [ 'A' , root . tagId ( ) , "" ] ) ;
551+ expect ( reply2 . tags ) . toContainEqual ( [ 'e' , reply1 . tagId ( ) , "" , reply1 . pubkey ] ) ;
552+ } ) ;
553+
554+ it ( "adds a 'K' tag to specify the root kind" , async ( ) => {
555+ const reply1 = await reply ( root , signers [ 1 ] ) ;
556+ expect ( reply1 . tags ) . toContainEqual ( [ 'K' , root . kind ! . toString ( ) ] ) ;
557+ } ) ;
558+
559+ it ( "adds a 'k' tag to specify the parent kind" , async ( ) => {
560+ const reply1 = await reply ( root , signers [ 1 ] ) ;
561+ const reply2 = reply1 . reply ( ) ;
562+ expect ( reply2 . tags ) . toContainEqual ( [ 'k' , reply1 . kind ! . toString ( ) ] ) ;
563+ } ) ;
564+ } ) ;
565+ } ) ;
566+
436567} ) ;
0 commit comments