Skip to main content

softchat/
lib.rs

1//! Portable Softchat protocol values and cryptographic operations.
2//!
3//! The native API uses validated values and retained capabilities. Callers
4//! construct protocol data explicitly: signing does not read a hidden clock or
5//! normalize exact Nostr tag arrays.
6//!
7//! # Protocol workflow
8//!
9//! ```
10//! use softchat::{
11//!     LocalIdentity, NostrEventDraft, NostrEventKind, NostrTag,
12//!     SignedNostrEvent,
13//! };
14//!
15//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
16//! let alice = LocalIdentity::from_secret_hex(
17//!     "5c0c523f52a5b6fad39ed2403092df8cebc36318b39383bca6c00808626fab3a",
18//! )?;
19//! let bob = LocalIdentity::from_secret_hex(
20//!     "4b22aa260e4acb7021e32f38a6cdf4b673c6a277755bfce287e370c924dc936d",
21//! )?;
22//!
23//! let encrypted = alice.encrypt_utf8(&bob.public_key(), "hello")?;
24//! assert_eq!(bob.decrypt_utf8(&encrypted)?, "hello");
25//!
26//! let recipient = NostrTag::new(vec![
27//!     "p".to_owned(),
28//!     bob.public_key().to_hex(),
29//!     String::new(),
30//!     String::new(),
31//! ])?;
32//! let draft = NostrEventDraft::new(
33//!     1_700_000_000,
34//!     NostrEventKind::SHORT_TEXT_NOTE,
35//!     vec![recipient],
36//!     "A signed protocol event",
37//! )?;
38//! let authored = alice.sign_event(draft)?;
39//! let received = SignedNostrEvent::from_json(&authored.to_json()?)?;
40//! assert_eq!(received, authored);
41//! # Ok(())
42//! # }
43//! ```
44//!
45//! The keys above are fixtures. Never use them outside tests or examples.
46//! Network transport, persistence, files, and application lifecycle remain
47//! platform-owned.
48
49mod account;
50mod chat;
51mod core;
52mod diagnostics;
53mod envelope;
54mod error;
55mod event;
56mod external_signer;
57mod facade;
58#[cfg(all(feature = "android-jni", target_os = "android"))]
59mod jni;
60mod media;
61mod message;
62mod negentropy;
63mod nip17;
64mod nip19;
65mod nip44_profile;
66mod noise;
67#[cfg(feature = "performance-probes")]
68mod performance_probes;
69mod relay;
70mod session;
71
72#[cfg(all(feature = "javascript-bindings", target_arch = "wasm32"))]
73mod wasm;
74
75pub use account::{
76    AppDataContext, AppDataSyncView, ApplicationDataView, Contact, FollowListView,
77    MAX_APP_DATA_JSON_BYTES, MAX_CONTACTS, UserMetadataView, classify_application_data,
78    classify_follow_list, classify_user_metadata, latest_application_data, latest_user_metadata,
79};
80pub use chat::{
81    ChatMessageDraft, ChatMessageView, ChatRelation, ChatRelationInput, ChatRelationKind,
82    DeletionView, EditView, GenericRepostView, MAX_CHAT_EMOJI_TAGS, MAX_CHAT_EXTENSION_TAGS,
83    MAX_CHAT_PARTICIPANTS, MessageProjection, ReactionDraft, ReactionView, SubjectDraft,
84    SubjectView, TypingView, classify_chat_message, classify_deletion, classify_edit,
85    classify_generic_repost, classify_reaction, classify_subject, classify_typing,
86    project_chat_message,
87};
88pub use core::{
89    LocalIdentity, MAX_CIPHERTEXT_BYTES, MAX_NIP44_BINARY_WRITER_PLAINTEXT_BYTES,
90    MAX_NIP44_ENCODED_PAYLOAD_BYTES, MAX_NIP44_READER_PLAINTEXT_BYTES,
91    MAX_NIP44_WRITER_PLAINTEXT_BYTES, MAX_PLAINTEXT_BYTES, NIP44_V2_ALGORITHM,
92    Nip44EncryptedMessage, Nip44Payload, NostrPublicKey,
93};
94pub use diagnostics::{
95    BuildFingerprint, DiagnosticsSnapshot, build_fingerprint, diagnostics_snapshot,
96};
97pub use envelope::{MAX_NIP59_TIMESTAMP_TWEAK_SECONDS, Nip59EnvelopeKind, UnwrappedNip59Envelope};
98pub use error::SoftchatError;
99pub use event::{
100    MAX_NOSTR_EVENT_JSON_BYTES, MAX_PORTABLE_TIMESTAMP_SECONDS, NostrEventDraft, NostrEventId,
101    NostrEventKind, NostrEventSignature, NostrRumor, NostrTag, SignedNostrEvent,
102};
103pub use external_signer::{
104    ExternalEventSigningRequest, ExternalSigner, ExternalSignerCapabilities, ExternalSignerFailure,
105    complete_external_event_signing, decrypt_with_external, encrypt_with_external,
106    prepare_external_event_signing, sign_event_with_external,
107};
108pub use facade::{ChatMessageInput, ReactionInput, SubjectInput, UserMetadataInput};
109pub use media::{
110    AttachmentDecryptionStream, AttachmentEncryptionStream, AttachmentMetadata,
111    AttachmentStreamFinal, HttpAuthorizationPlan, MAX_ATTACHMENT_COMPATIBILITY_BYTES,
112    MAX_ATTACHMENT_FALLBACKS, MAX_ATTACHMENT_METADATA_FIELDS, MAX_ATTACHMENT_STREAM_BYTES,
113    MAX_ATTACHMENT_STREAM_CHUNK_BYTES, create_nip98_authorization, decrypt_attachment_bytes,
114    encrypt_attachment_bytes, parse_attachment_metadata,
115};
116pub use message::version;
117pub use negentropy::{
118    MAX_NEGENTROPY_FRAME_BYTES, MAX_NEGENTROPY_ITEMS, MIN_NEGENTROPY_FRAME_BYTES, NegentropyClient,
119    NegentropyItem, NegentropyStep,
120};
121pub use nip17::Nip17TextMessage;
122pub use nip19::{
123    MAX_NIP19_IDENTIFIER_CHARS, MAX_NIP19_RELAYS, Nip19Identifier, Nip19IdentifierKind, Nip19Tlv,
124};
125pub use noise::{
126    MAX_NOISE_FRAME_CIPHERTEXT, MAX_NOISE_FRAME_PLAINTEXT, MAX_NOISE_MESSAGE_SIZE,
127    NOISE_PROTOCOL_NAME, NoiseClientHandshake, NoiseTransport,
128};
129#[cfg(feature = "performance-probes")]
130#[doc(hidden)]
131pub use performance_probes::{
132    Nip44PerformanceProbe, performance_consume_string, performance_echo_string,
133    performance_produce_string,
134};
135pub use relay::{
136    BatchAcknowledgement, BatchEventState, BatchProgress, ClientRelayFrame, MAX_RELAY_BATCH_EVENTS,
137    MAX_RELAY_FILTER_VALUES, MAX_RELAY_FILTERS, MAX_RELAY_FRAME_BYTES, MAX_RELAY_MESSAGE_CHARS,
138    MAX_SUBSCRIPTION_ID_CHARS, NIP42_AUTH_WINDOW_SECONDS, RelayFilter, RelayResponseFrame,
139    encode_events_frame, parse_client_relay_frame, parse_relay_response_frame,
140    plan_nip42_authentication, track_batch_acknowledgements, validate_nip42_authentication,
141};
142pub use session::{
143    DeliveryDecision, DeliveryState, IngestionBatch, IngestionResult, MAX_INFLIGHT_INGESTION,
144    MAX_OUTBOUND_RELAY_FRAMES, MAX_PENDING_PUBLISHES, MAX_RELAY_SUBSCRIPTIONS, PersistenceAdapter,
145    RelayConnectionState, RelaySession, RelaySessionAction, RelaySessionActionKind,
146    RelaySessionHandle, RelaySessionSnapshot, classify_delivery_acknowledgement,
147    validate_ingestion_result,
148};
149
150#[doc(hidden)]
151pub use envelope::UnwrappedEnvelope;
152#[doc(hidden)]
153pub use event::{
154    EventDraft, RumorEvent, SignedEvent, nostr_rumor_json, parse_nostr_rumor_json,
155    parse_signed_nostr_event_json, signed_nostr_event_json, validate_nostr_event_draft,
156    validate_nostr_event_id, validate_nostr_event_kind, validate_nostr_event_signature,
157    validate_nostr_rumor, validate_nostr_tag, validate_signed_nostr_event,
158};
159#[doc(hidden)]
160pub use message::{
161    EncryptedMessage, ImportedLocalIdentity, LocalIdentityHandle, decrypt_message, encrypt_message,
162    import_local_identity, public_key, validate_encrypted_message, validate_public_key,
163};
164#[doc(hidden)]
165pub use nip17::{Nip17Message, validate_nip17_text_message};
166#[doc(hidden)]
167pub use nip19::{Nip19Value, encode_nip19_identifier, parse_nip19_identifier};
168
169#[cfg(feature = "native-bindings")]
170uniffi::setup_scaffolding!();