CakeWallet/cw_bitcoin/lib/payjoin/storage.dart
Konstantin Ullrich 4b137bc968
CW-1091-payjoin-error-handeling (#2317)
* feat: stop polling payjoin on switch wallet

* refactor: improve Payjoin session handling and cleanup unused methods

- Replaced `initReceiver` with `getUnusedReceiver` to reuse existing Payjoin sessions.
- Streamlined session initialization by removing `spawnNewReceiver`.
- Adjusted wallet sync reactions to resume Payjoin sessions when necessary.

* fix: Receiver.fromJson correctly handle parameter format in Payjoin manager

* fix: try reloading unspents if unspents are empty; No Unpsents available are now recoverable errors

* fix: ensure transaction details display only if transactionInfo is available and adjust payjoin success status handling

* fix: adjust payjoin success status handling for pending transactions

* fix: add error handling for Payjoin initialization and receiver creation [skip-ci]

* fix: add unrecoverable error handling for Payjoin sender sessions
2025-06-19 19:55:41 +03:00

104 lines
3.2 KiB
Dart

import 'package:cw_core/payjoin_session.dart';
import 'package:hive/hive.dart';
import 'package:payjoin_flutter/receive.dart';
import 'package:payjoin_flutter/send.dart';
class PayjoinStorage {
PayjoinStorage(this._payjoinSessionSources);
final Box<PayjoinSession> _payjoinSessionSources;
static const String _receiverPrefix = 'pj_recv_';
static const String _senderPrefix = 'pj_send_';
Future<void> insertReceiverSession(
Receiver receiver,
String walletId,
) =>
_payjoinSessionSources.put(
"$_receiverPrefix${receiver.id()}",
PayjoinSession(
walletId: walletId,
receiver: receiver.toJson(),
),
);
PayjoinSession? getUnusedActiveReceiverSession(String walletId) =>
_payjoinSessionSources.values
.where((session) =>
session.walletId == walletId &&
session.status == PayjoinSessionStatus.created.name &&
!session.isSenderSession)
.firstOrNull;
Future<void> markReceiverSessionComplete(
String sessionId, String txId, String amount) async {
final session = _payjoinSessionSources.get("$_receiverPrefix${sessionId}")!;
session.status = PayjoinSessionStatus.success.name;
session.txId = txId;
session.rawAmount = amount;
await session.save();
}
Future<void> markReceiverSessionUnrecoverable(
String sessionId, String reason) async {
final session = _payjoinSessionSources.get("$_receiverPrefix${sessionId}")!;
session.status = PayjoinSessionStatus.unrecoverable.name;
session.error = reason;
await session.save();
}
Future<void> markReceiverSessionInProgress(String sessionId) async {
final session = _payjoinSessionSources.get("$_receiverPrefix${sessionId}")!;
session.status = PayjoinSessionStatus.inProgress.name;
session.inProgressSince = DateTime.now();
await session.save();
}
Future<void> insertSenderSession(
Sender sender,
String pjUrl,
String walletId,
BigInt amount,
) =>
_payjoinSessionSources.put(
"$_senderPrefix$pjUrl",
PayjoinSession(
walletId: walletId,
pjUri: pjUrl,
sender: sender.toJson(),
status: PayjoinSessionStatus.inProgress.name,
inProgressSince: DateTime.now(),
rawAmount: amount.toString(),
),
);
Future<void> markSenderSessionComplete(String pjUrl, String txId) async {
final session = _payjoinSessionSources.get("$_senderPrefix$pjUrl")!;
session.status = PayjoinSessionStatus.success.name;
session.txId = txId;
await session.save();
}
Future<void> markSenderSessionUnrecoverable(String pjUrl, String reason) async {
final session = _payjoinSessionSources.get("$_senderPrefix$pjUrl")!;
session.status = PayjoinSessionStatus.unrecoverable.name;
session.error = reason;
await session.save();
}
List<PayjoinSession> readAllOpenSessions(String walletId) =>
_payjoinSessionSources.values
.where((session) =>
session.walletId == walletId &&
![
PayjoinSessionStatus.success.name,
PayjoinSessionStatus.unrecoverable.name
].contains(session.status))
.toList();
}