From b867fa783ef6af4b601cd671155677190d10683d Mon Sep 17 00:00:00 2001 From: Kayos Date: Sat, 28 Mar 2026 07:26:08 -0700 Subject: [PATCH] =?UTF-8?q?feat(wallet):=20wire=20real=20sendRaw()=20?= =?UTF-8?q?=E2=80=94=20Phase=202=20complete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - RustTimeline.sendRaw() now calls inner.sendRaw() via custom SDK .aar - DefaultPaymentEventSender fully implemented: serializes payment data as JSON, sends co.sulkta.payment.request and co.sulkta.payment.status event types - matrix-rust-sdk.aar built from sulkta/send-raw-v1 fork with UniFFI binding - Removes UnsupportedOperationException stub — payments now actually send --- .../impl/payment/DefaultPaymentEventSender.kt | 41 ++++++++----------- .../matrix/impl/timeline/RustTimeline.kt | 15 ++++--- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/features/wallet/impl/src/main/kotlin/io/element/android/features/wallet/impl/payment/DefaultPaymentEventSender.kt b/features/wallet/impl/src/main/kotlin/io/element/android/features/wallet/impl/payment/DefaultPaymentEventSender.kt index 15776c25bb..c618ee6682 100644 --- a/features/wallet/impl/src/main/kotlin/io/element/android/features/wallet/impl/payment/DefaultPaymentEventSender.kt +++ b/features/wallet/impl/src/main/kotlin/io/element/android/features/wallet/impl/payment/DefaultPaymentEventSender.kt @@ -20,11 +20,8 @@ import kotlinx.serialization.json.Json /** * Default implementation of [PaymentEventSender]. * - * Since the Matrix SDK does not expose raw event sending, we send payment data - * as a structured message with a recognizable prefix that can be parsed by the UI. - * - * Message format: $CARDANO_PAY${json} - * This allows the timeline UI to render a payment card instead of raw text. + * Sends Cardano payment events as custom Matrix event types via Timeline.sendRaw(). + * Events go through the send queue for reliability and encryption support. */ @ContributesBinding(SessionScope::class) class DefaultPaymentEventSender @Inject constructor() : PaymentEventSender { @@ -50,16 +47,11 @@ class DefaultPaymentEventSender @Inject constructor() : PaymentEventSender { ) val jsonContent = json.encodeToString(paymentData) - val message = "$PAYMENT_MESSAGE_PREFIX$jsonContent" - // Send as a regular message - the timeline renderer will recognize the prefix - return runCatching { - timeline.sendMessage( - body = message, - htmlBody = null, - intentionalMentions = emptyList(), - ) - } + return timeline.sendRaw( + eventType = EVENT_TYPE_PAYMENT_REQUEST, + content = jsonContent, + ) } override suspend fun sendStatusUpdate( @@ -75,21 +67,22 @@ class DefaultPaymentEventSender @Inject constructor() : PaymentEventSender { ) val jsonContent = json.encodeToString(statusData) - val message = "$STATUS_MESSAGE_PREFIX$jsonContent" - return runCatching { - timeline.sendMessage( - body = message, - htmlBody = null, - intentionalMentions = emptyList(), - ) - } + return timeline.sendRaw( + eventType = EVENT_TYPE_PAYMENT_STATUS, + content = jsonContent, + ) } companion object { - /** Prefix for payment messages - UI parses this to render payment cards */ + /** Matrix event type for Cardano payment requests */ + const val EVENT_TYPE_PAYMENT_REQUEST = "co.sulkta.payment.request" + /** Matrix event type for payment status updates */ + const val EVENT_TYPE_PAYMENT_STATUS = "co.sulkta.payment.status" + + /** Legacy prefix for payment messages - kept for backward compatibility */ const val PAYMENT_MESSAGE_PREFIX = "\$CARDANO_PAY$" - /** Prefix for status update messages */ + /** Legacy prefix for status update messages - kept for backward compatibility */ const val STATUS_MESSAGE_PREFIX = "\$CARDANO_STATUS$" } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt index 1de0bfd189..df7bd0442d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt @@ -280,15 +280,20 @@ class RustTimeline( } /** - * Send a raw/custom event. Currently not supported by the Rust SDK bindings. - * The SDK Timeline does not expose sendRaw - custom events must use message markers for now. + * Send a raw/custom event to the room. + * + * @param eventType The event type (e.g., "co.sulkta.payment.request") + * @param content The JSON content of the event + * @return Result indicating success or failure */ override suspend fun sendRaw( eventType: String, content: String, - ): Result { - // The Rust SDK Timeline interface does not expose sendRaw yet. - return Result.failure(UnsupportedOperationException("sendRaw not yet supported by Matrix Rust SDK bindings")) + ): Result = withContext(dispatcher) { + runCatchingExceptions { + inner.sendRaw(eventType, content) + Unit + } } override suspend fun redactEvent(eventOrTransactionId: EventOrTransactionId, reason: String?): Result = withContext(dispatcher) {