#pragma once #include #include #include #ifndef DRAGONX_ENABLE_CHAT #define DRAGONX_ENABLE_CHAT 0 #endif namespace dragonx::chat { enum class HushChatHeaderType { Message, ContactRequest }; struct HushChatHeader { int header_number = 0; int version = 0; std::string reply_zaddr; std::string conversation_id; HushChatHeaderType type = HushChatHeaderType::Message; std::string secretstream_header_hex; std::string public_key_hex; // Optional sender-stamped compose time (header "ts", Unix seconds). 0 = absent (older sender) → the // receiver falls back to the tx/receive time. Lets both sides show the SAME (send) time. std::int64_t sent_at = 0; }; struct HushChatHeaderParseResult { bool ok = false; HushChatHeader header; std::string error; }; struct HushChatMemoOutput { std::size_t position = 0; std::string memo; }; struct HushChatMemoPair { HushChatHeader header; std::size_t header_position = 0; std::size_t payload_position = 0; std::string payload_memo; }; enum class HushChatMemoGroupingIssue { InvalidHeader, MissingPayload, DuplicateHeader, OversizedMemo }; struct HushChatMemoGroupingIssueInfo { HushChatMemoGroupingIssue issue = HushChatMemoGroupingIssue::InvalidHeader; std::size_t position = 0; std::string detail; }; struct HushChatMemoGroupingResult { std::vector pairs; std::vector issues; std::size_t ignored_memo_count = 0; }; struct HushChatTransactionInput { std::string txid; std::vector outputs; }; struct HushChatTransactionMetadata { std::string txid; HushChatHeaderType type = HushChatHeaderType::Message; std::string conversation_id; std::string reply_zaddr; std::size_t header_position = 0; std::size_t payload_position = 0; std::size_t payload_size = 0; // Decrypt inputs carried through from the paired header + payload memos so the chat // service can actually decrypt (a Message) or read the request (a ContactRequest). std::string sender_public_key_hex; // header "p": peer crypto_kx public key (hex) std::string secretstream_header_hex; // header "e": secretstream header (hex; empty for ContactRequest) std::string payload_memo; // ciphertext hex (Message) or plaintext request text (ContactRequest) std::int64_t sent_at = 0; // header "ts": sender compose time (Unix s); 0 = absent → use tx time }; struct HushChatTransactionExtractionResult { bool feature_enabled = false; std::vector metadata; std::vector issues; std::size_t ignored_memo_count = 0; }; constexpr int kHushChatSupportedVersion = 0; constexpr std::size_t kHushChatMemoByteLimit = 512; constexpr std::size_t kHushChatPublicKeyHexLength = 64; constexpr std::size_t kHushChatSecretstreamHeaderHexLength = 48; constexpr bool hushChatFeatureEnabledAtBuild() { return DRAGONX_ENABLE_CHAT != 0; } HushChatHeaderParseResult parseHushChatHeaderMemo(const std::string& memo); HushChatMemoGroupingResult groupHushChatMemoOutputs(const std::vector& outputs); HushChatTransactionExtractionResult extractHushChatTransactionMetadata( const HushChatTransactionInput& transaction, bool featureEnabled = hushChatFeatureEnabledAtBuild()); const char* hushChatHeaderTypeName(HushChatHeaderType type); const char* hushChatMemoGroupingIssueName(HushChatMemoGroupingIssue issue); } // namespace dragonx::chat