wire.rs (3140B)
1 use radroots_event::GenericEventDraft; 2 use radroots_event::draft::DraftError; 3 use radroots_event::envelope::kind::{KIND_GEOCHAT, KIND_PROFILE, KIND_RHI_EVIDENCE_ATTESTATION}; 4 use radroots_event::wire::Nip01EventWireParts; 5 use radroots_event_codec::decode::wire::{canonicalize_tags, empty_content}; 6 7 #[test] 8 fn wire_canonicalize_tags_trims_sorts_and_dedups() { 9 let mut tags = vec![ 10 vec![" z ".to_string(), "b".to_string()], 11 vec!["t".to_string(), "a".to_string()], 12 vec!["".to_string(), "x".to_string()], 13 vec![" t ".to_string(), "a ".to_string()], 14 vec!["t".to_string(), "a".to_string()], 15 ]; 16 17 canonicalize_tags(&mut tags); 18 19 assert_eq!( 20 tags, 21 vec![ 22 vec!["t".to_string(), "a".to_string()], 23 vec!["z".to_string(), "b".to_string()], 24 ] 25 ); 26 } 27 28 #[test] 29 fn wire_parts_are_canonical_event_owned_payload_parts() { 30 let parts = Nip01EventWireParts { 31 kind: KIND_GEOCHAT, 32 content: "hello".to_string(), 33 tags: vec![vec!["t".to_string(), "a".to_string()]], 34 }; 35 let json = serde_json::to_string(&parts).expect("json"); 36 let decoded: Nip01EventWireParts = serde_json::from_str(&json).expect("decoded"); 37 38 assert_eq!(decoded, parts); 39 } 40 41 #[test] 42 fn draft_validation_accepts_wire_parts_without_signed_envelope() { 43 let parts = Nip01EventWireParts { 44 kind: KIND_GEOCHAT, 45 content: "hello".to_string(), 46 tags: vec![vec!["t".to_string(), "a".to_string()]], 47 }; 48 49 let draft = GenericEventDraft::new( 50 "radroots.social.geochat.v1", 51 parts.kind, 52 99, 53 parts.tags, 54 parts.content, 55 "a".repeat(64), 56 ) 57 .expect("draft"); 58 59 assert_eq!(draft.kind_u32(), KIND_GEOCHAT); 60 assert_eq!(draft.created_at_u64(), 99); 61 assert_eq!(draft.expected_pubkey().to_hex(), "a".repeat(64)); 62 assert_eq!(draft.content(), "hello"); 63 assert_eq!(draft.tags().len(), 1); 64 assert_eq!(draft.expected_event_id_hex().len(), 64); 65 } 66 67 #[test] 68 fn generic_draft_rejects_typed_only_contracts() { 69 let typed_only = Nip01EventWireParts { 70 kind: KIND_PROFILE, 71 content: r#"{"name":"Alice"}"#.to_string(), 72 tags: Vec::new(), 73 }; 74 let error = GenericEventDraft::new( 75 "radroots.profile.metadata.v1", 76 typed_only.kind, 77 99, 78 typed_only.tags, 79 typed_only.content, 80 "a".repeat(64), 81 ) 82 .expect_err("typed-only contract"); 83 assert!(matches!( 84 error, 85 DraftError::ContractNotDraftAuthorable { .. } 86 )); 87 } 88 89 #[test] 90 fn generic_draft_rejects_the_typed_only_rhi_attestation_contract() { 91 let error = GenericEventDraft::new( 92 "radroots.rhi.evidence_attestation.v1", 93 KIND_RHI_EVIDENCE_ATTESTATION, 94 99, 95 Vec::new(), 96 "{}", 97 "a".repeat(64), 98 ) 99 .expect_err("RHI attestation requires the typed authoring path"); 100 assert!(matches!( 101 error, 102 DraftError::ContractNotDraftAuthorable { .. } 103 )); 104 } 105 106 #[test] 107 fn wire_empty_content_is_empty_string() { 108 let content = empty_content(); 109 assert!(content.is_empty()); 110 }