Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions android/app/src/main/java/org/bitcoinppl/cove_core/cove.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53081,6 +53081,9 @@ sealed class WalletDataKey {
object ReceiveAddressCache : WalletDataKey()


object PayjoinSenderSession : WalletDataKey()





Expand All @@ -53101,6 +53104,7 @@ public object FfiConverterTypeWalletDataKey : FfiConverterRustBuffer<WalletDataK
FfiConverterTypeWalletAddressType.read(buf),
)
2 -> WalletDataKey.ReceiveAddressCache
3 -> WalletDataKey.PayjoinSenderSession
else -> throw RuntimeException("invalid enum value, something is very wrong!!")
}
}
Expand All @@ -53119,6 +53123,12 @@ public object FfiConverterTypeWalletDataKey : FfiConverterRustBuffer<WalletDataK
4UL
)
}
is WalletDataKey.PayjoinSenderSession -> {
// Add the size for the Int that specifies the variant plus the size needed for all fields
(
4UL
)
}
}

override fun write(value: WalletDataKey, buf: ByteBuffer) {
Expand All @@ -53132,6 +53142,10 @@ public object FfiConverterTypeWalletDataKey : FfiConverterRustBuffer<WalletDataK
buf.putInt(2)
Unit
}
is WalletDataKey.PayjoinSenderSession -> {
buf.putInt(3)
Unit
}
}.let { /* this makes the `when` an expression, which ensures it is exhaustive */ }
}
}
Expand Down
7 changes: 7 additions & 0 deletions ios/CoveCore/Sources/CoveCore/generated/cove.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33936,6 +33936,7 @@ public enum WalletDataKey: Equatable, Hashable {
case scanState(WalletAddressType
)
case receiveAddressCache
case payjoinSenderSession



Expand All @@ -33962,6 +33963,8 @@ public struct FfiConverterTypeWalletDataKey: FfiConverterRustBuffer {

case 2: return .receiveAddressCache

case 3: return .payjoinSenderSession

default: throw UniffiInternalError.unexpectedEnumCase
}
}
Expand All @@ -33978,6 +33981,10 @@ public struct FfiConverterTypeWalletDataKey: FfiConverterRustBuffer {
case .receiveAddressCache:
writeInt(&buf, Int32(2))


case .payjoinSenderSession:
writeInt(&buf, Int32(3))

}
}
}
Expand Down
97 changes: 97 additions & 0 deletions rust/src/database/wallet_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@ pub enum WalletData {
/// number of addresses scanned
ScanState(ScanState),
ReceiveAddressCache(ReceiveAddressCache),
PayjoinSenderSession(PayjoinSenderSession),
}

#[derive(Debug, Clone, Serialize, Deserialize, uniffi::Enum)]
pub enum WalletDataKey {
ScanState(WalletAddressType),
ReceiveAddressCache,
PayjoinSenderSession,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, uniffi::Enum)]
Expand Down Expand Up @@ -79,6 +81,39 @@ impl ReceiveAddressCache {
}
}

/// Consensus-encoded bytes of a bitcoin transaction stored in the database.
///
/// `bitcoin::Transaction` does not implement serde natively; storing the consensus-encoded
/// bytes avoids an orphan-impl problem while keeping the format identical to what is broadcast.
#[derive(
Debug, Clone, Serialize, Deserialize, Eq, PartialEq, derive_more::From, derive_more::Into,
)]
pub struct TransactionBytes(Vec<u8>);

impl AsRef<[u8]> for TransactionBytes {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
Comment on lines +93 to +97

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think derive_more as an AsRef


/// Terminal action decided for a payjoin session before the broadcast completes
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
pub enum PendingAction {
BroadcastFallback,
BroadcastProposal { transaction: TransactionBytes },
}

/// Event log for an in-flight payjoin sender session, allowing it to survive app restarts
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
pub struct PayjoinSenderSession {
pub events: Vec<String>,
pub fallback_tx: TransactionBytes,
#[serde(default)]
pub created_at_secs: Option<u64>,
#[serde(default)]
pub pending_action: Option<PendingAction>,
}
Comment thread
Sandipmandal25 marked this conversation as resolved.

#[derive(Debug, Clone, uniffi::Object)]
pub struct WalletDataDb {
pub id: WalletId,
Expand Down Expand Up @@ -179,6 +214,24 @@ impl WalletDataDb {
self.delete(WalletDataKey::ReceiveAddressCache)
}

pub fn get_payjoin_sender_session(&self) -> Result<Option<PayjoinSenderSession>> {
let value = self.get(WalletDataKey::PayjoinSenderSession)?;

let Some(WalletData::PayjoinSenderSession(session)) = value else {
return Ok(None);
};

Ok(Some(session))
}

pub fn set_payjoin_sender_session(&self, session: PayjoinSenderSession) -> Result<()> {
self.set(WalletDataKey::PayjoinSenderSession, WalletData::PayjoinSenderSession(session))
}

pub fn delete_payjoin_sender_session(&self) -> Result<()> {
self.delete(WalletDataKey::PayjoinSenderSession)
}

fn get(&self, key: WalletDataKey) -> Result<Option<WalletData>> {
let table = self.read_table()?;

Expand Down Expand Up @@ -298,6 +351,7 @@ impl WalletDataKey {
Self::ScanState(WalletAddressType::WrappedSegwit) => "scan_state_wrapped_segwit",
Self::ScanState(WalletAddressType::Legacy) => "scan_state_legacy",
Self::ReceiveAddressCache => "receive_address_cache",
Self::PayjoinSenderSession => "payjoin_sender_session",
}
}
}
Expand Down Expand Up @@ -396,4 +450,47 @@ mod tests {

assert_eq!(db.get_receive_address_cache().unwrap(), None);
}

#[test]
fn payjoin_sender_session_round_trips() {
let wallet_id = WalletId::preview_new_random();
let (db, _tmp) = test_support::new_test_wallet_data_db(wallet_id);
let session = PayjoinSenderSession {
events: vec![r#"{"PostedOriginalPsbt":[]}"#.to_string()],
fallback_tx: vec![0x02, 0x00, 0x00, 0x00].into(),
created_at_secs: None,
pending_action: None,
};

db.set_payjoin_sender_session(session.clone()).unwrap();

assert_eq!(db.get_payjoin_sender_session().unwrap(), Some(session));
}

#[test]
fn delete_payjoin_sender_session_clears_session() {
let wallet_id = WalletId::preview_new_random();
let (db, _tmp) = test_support::new_test_wallet_data_db(wallet_id);
let session = PayjoinSenderSession {
events: vec![r#"{"Closed":"Failure"}"#.to_string()],
fallback_tx: vec![0x02, 0x00, 0x00, 0x00].into(),
created_at_secs: None,
pending_action: None,
};

db.set_payjoin_sender_session(session).unwrap();
db.delete_payjoin_sender_session().unwrap();

assert_eq!(db.get_payjoin_sender_session().unwrap(), None);
}

#[test]
fn delete_missing_payjoin_sender_session_succeeds() {
let wallet_id = WalletId::preview_new_random();
let (db, _tmp) = test_support::new_test_wallet_data_db(wallet_id);

db.delete_payjoin_sender_session().unwrap();

assert_eq!(db.get_payjoin_sender_session().unwrap(), None);
}
}
Loading
Loading