diff --git a/cw_bitcoin/lib/bitcoin_payjoin.dart b/cw_bitcoin/lib/bitcoin_payjoin.dart
index c400ba457..166e78cd7 100644
--- a/cw_bitcoin/lib/bitcoin_payjoin.dart
+++ b/cw_bitcoin/lib/bitcoin_payjoin.dart
@@ -143,7 +143,6 @@ class BitcoinPayjoin {
     }
   }
 
-  Future<PendingBitcoinTransaction> extractPjTx(
-          Object wallet, String psbtString, Object credentials) async =>
-      (wallet as BitcoinWallet).psbtToPendingTx(psbtString, credentials);
+  Future<PendingBitcoinTransaction> extractPjTx(Object wallet, String psbtString) async =>
+      (wallet as BitcoinWallet).psbtToPendingTx(psbtString);
 }
diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart
index 9d89da466..ec6b0ec45 100644
--- a/cw_bitcoin/lib/bitcoin_wallet.dart
+++ b/cw_bitcoin/lib/bitcoin_wallet.dart
@@ -85,7 +85,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
     // String sideDerivationPath = derivationPath.substring(0, derivationPath.length - 1) + "1";
     // final hd = bitcoin.HDWallet.fromSeed(seedBytes, network: networkType);
 
-    payjoinManager = PayjoinManager(PayjoinStorage(payjoinSessionSources: payjoinBox), this);
+    payjoinManager = PayjoinManager(PayjoinStorage(payjoinBox), this);
     walletAddresses = BitcoinWalletAddresses(
       walletInfo,
       initialAddresses: initialAddresses,
@@ -339,43 +339,36 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
   @override
   Future<PendingTransaction> createTransaction(Object credentials) async {
     credentials = credentials as BitcoinTransactionCredentials;
-    final tx =
-        super.createTransaction(credentials) as PendingBitcoinTransaction;
 
-    // if (credentials.payjoinUri == null) return tx;
-    //
-    // final transaction = await buildPsbt(
-    //     utxos: tx.utxos,
-    //     outputs: tx.outputs.map((e) => BitcoinOutput(
-    //       address: BitcoinBaseAddress.fromString(e.scriptPubKey.toAddress()),
-    //       value: e.amount,
-    //       isSilentPayment: e.isSilentPayment,
-    //       isChange: e.isChange,
-    //     )).toList(),
-    //     fee: BigInt.from(tx.fee),
-    //     network: network,
-    //     memo: credentials.outputs.first.memo,
-    //     outputOrdering: BitcoinOrdering.none,
-    //     enableRBF: true,
-    //     publicKeys: tx.publicKeys,
-    //     masterFingerprint: Uint8List(0)
-    // );
-    //
-    // transaction.signWithUTXO(
-    //     tx.utxos
-    //         .map((e) =>
-    //         UtxoWithPrivateKey.fromUtxo(e, tx.inputPrivKeyInfos))
-    //         .toList(), (txDigest, utxo, key, sighash) {
-    //   if (utxo.utxo.isP2tr()) {
-    //     return key.signTapRoot(
-    //       txDigest,
-    //       sighash: sighash,
-    //       tweak: utxo.utxo.isSilentPayment != true,
-    //     );
-    //   } else {
-    //     return key.signInput(txDigest, sigHash: sighash);
-    //   }
-    // });
+    final tx = (await super.createTransaction(credentials)) as PendingBitcoinTransaction;
+
+    final payjoinUri = credentials.payjoinUri;
+    if (payjoinUri == null) return tx;
+
+    final transaction = await buildPsbt(
+        utxos: tx.utxos,
+        outputs: tx.outputs.map((e) => BitcoinOutput(
+          address: BitcoinBaseAddress.fromString(e.scriptPubKey.toAddress()),
+          value: e.amount,
+          isSilentPayment: e.isSilentPayment,
+          isChange: e.isChange,
+        )).toList(),
+        fee: BigInt.from(tx.fee),
+        network: network,
+        memo: credentials.outputs.first.memo,
+        outputOrdering: BitcoinOrdering.none,
+        enableRBF: true,
+        publicKeys: tx.publicKeys!,
+        masterFingerprint: Uint8List(0)
+    );
+
+    final originalPsbt = await signPsbt(base64.encode(transaction.asPsbtV0()), getUtxoWithPrivateKeys());
+
+    tx.commitOverride = () async {
+      final sender =
+          await payjoinManager.initSender(payjoinUri, originalPsbt, tx.fee);
+      await payjoinManager.spawnNewSender(sender: sender, pjUrl: payjoinUri);
+    };
 
     return tx;
   }
@@ -497,8 +490,25 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
       .map((unspent) => UtxoWithPrivateKey.fromUnspent(unspent, this))
       .toList();
 
-  Future<PendingBitcoinTransaction> psbtToPendingTx(
-      String preProcessedPsbt, Object credentials) async {
+  Future<void> commitPsbt(String finalizedPsbt) {
+    final psbt = PsbtV2()..deserializeV0(base64.decode(finalizedPsbt));
+
+    final btcTx =
+        BtcTransaction.fromRaw(BytesUtils.toHexString(psbt.extract()));
+
+    return PendingBitcoinTransaction(
+      btcTx,
+      type,
+      electrumClient: electrumClient,
+      amount: 0,
+      fee: 0,
+      feeRate: "",
+      network: network,
+      hasChange: true,
+    ).commit();
+  }
+
+  Future<PendingBitcoinTransaction> psbtToPendingTx(String preProcessedPsbt) async {
     final psbt = PsbtV2()..deserializeV0(base64.decode(preProcessedPsbt));
 
     final inputCount = psbt.getGlobalInputCount();
@@ -575,17 +585,6 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
     return base64Encode(psbt.asPsbtV0());
   }
 
-  Future<String> getPJURl() async {
-    final payjoinBox = await CakeHive.openBox<PayjoinSession>(PayjoinSession.boxName);
-    final manager = PayjoinManager(PayjoinStorage(payjoinSessionSources: payjoinBox), this);
-
-    final receiver = await manager.initReceiver(walletAddresses.primaryAddress);
-
-    manager.spawnNewReceiver(receiver: receiver);
-
-    return receiver.pjUriBuilder().build().pjEndpoint();
-  }
-
   @override
   Future<String> signMessage(String message, {String? address = null}) async {
     if (walletInfo.isHardwareWallet) {
diff --git a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart
index 83e895f90..cf6407248 100644
--- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart
+++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart
@@ -57,13 +57,12 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
   @override
   Future<void> init() async {
     await super.init();
-
-    refreshPayjoinReceiver();
   }
   
-  Future<void> refreshPayjoinReceiver() async {
+  Future<void> initPayjoin() async {
     currentPayjoinReceiver = await payjoinManager.initReceiver(primaryAddress);
-
+    
+    await payjoinManager.resumeSessions();
     await payjoinManager.spawnNewReceiver(receiver: currentPayjoinReceiver!);
   }
 }
diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart
index 09f200183..cf1729d50 100644
--- a/cw_bitcoin/lib/electrum_wallet.dart
+++ b/cw_bitcoin/lib/electrum_wallet.dart
@@ -1181,6 +1181,7 @@ abstract class ElectrumWalletBase
         isSendAll: estimatedTx.isSendAll,
         hasTaprootInputs: hasTaprootInputs,
         utxos: estimatedTx.utxos,
+        publicKeys: estimatedTx.publicKeys
       )..addListener((transaction) async {
           transactionHistory.addOne(transaction);
           if (estimatedTx.spendsSilentPayment) {
diff --git a/cw_bitcoin/lib/payjoin/manager.dart b/cw_bitcoin/lib/payjoin/manager.dart
index c9ab062c6..fc8a47120 100644
--- a/cw_bitcoin/lib/payjoin/manager.dart
+++ b/cw_bitcoin/lib/payjoin/manager.dart
@@ -5,12 +5,16 @@ import 'dart:typed_data';
 
 import 'package:bitcoin_base/bitcoin_base.dart';
 import 'package:cw_bitcoin/bitcoin_wallet.dart';
-import 'package:cw_bitcoin/payjoin/payjoin_worker.dart';
+import 'package:cw_bitcoin/payjoin/payjoin_receive_worker.dart';
+import 'package:cw_bitcoin/payjoin/payjoin_send_worker.dart';
+import 'package:cw_bitcoin/payjoin/payjoin_session_errors.dart';
 import 'package:cw_bitcoin/payjoin/storage.dart';
 import 'package:cw_bitcoin/psbt_signer.dart';
+import 'package:cw_core/utils/print_verbose.dart';
 import 'package:payjoin_flutter/common.dart';
 import 'package:payjoin_flutter/receive.dart';
-import 'package:payjoin_flutter/uri.dart';
+import 'package:payjoin_flutter/send.dart';
+import 'package:payjoin_flutter/uri.dart' as PayjoinUri;
 
 class PayjoinManager {
   PayjoinManager(this._payjoinStorage, this._wallet);
@@ -19,20 +23,133 @@ class PayjoinManager {
   final BitcoinWalletBase _wallet;
   final Map<String, PayjoinPollerSession> _activePollers = {};
 
-  static const List<String> _ohttpRelayUrls = [
+  static const List<String> ohttpRelayUrls = [
     'https://pj.bobspacebkk.com',
     'https://ohttp.achow101.com',
   ];
 
+  static Future<PayjoinUri.Url> randomOhttpRelayUrl() => PayjoinUri.Url.fromStr(
+      ohttpRelayUrls[Random.secure().nextInt(ohttpRelayUrls.length)]);
+
   static const payjoinDirectoryUrl = 'https://payjo.in';
 
+  Future<void> resumeSessions() async {
+    final allSessions = _payjoinStorage.readAllOpenSessions(_wallet.id);
+
+    final spawnedSessions = allSessions.map((session) {
+      if (session.isSenderSession) {
+        return spawnSender(
+          sender: Sender.fromJson(session.sender!),
+          pjUri: session.pjUri!,
+        );
+      }
+      return spawnReceiver(
+        receiver: Receiver.fromJson(session.receiver!),
+      );
+    });
+
+    await Future.wait(spawnedSessions);
+  }
+
+  Future<Sender> initSender(
+      String pjUriString, String originalPsbt, int networkFeesSatPerVb) async {
+    try {
+      final pjUri =
+          (await PayjoinUri.Uri.fromStr(pjUriString)).checkPjSupported();
+      final minFeeRateSatPerKwu = BigInt.from(networkFeesSatPerVb * 250);
+      final senderBuilder = await SenderBuilder.fromPsbtAndUri(
+        psbtBase64: originalPsbt,
+        pjUri: pjUri,
+      );
+      return senderBuilder.buildRecommended(minFeeRate: minFeeRateSatPerKwu);
+    } catch (e) {
+      throw Exception('Error initializing Payjoin Sender: $e');
+    }
+  }
+
+  Future<void> spawnNewSender({
+    required Sender sender,
+    required String pjUrl,
+    bool isTestnet = false,
+  }) async {
+    await _payjoinStorage.insertSenderSession(
+      sender,
+      pjUrl,
+      _wallet.id,
+    );
+
+    return spawnSender(
+      isTestnet: isTestnet,
+      sender: sender,
+      pjUri: pjUrl,
+    );
+  }
+
+  Future<void> spawnSender({
+    required Sender sender,
+    required String pjUri,
+    bool isTestnet = false,
+  }) async {
+    final completer = Completer();
+    final receivePort = ReceivePort();
+
+    receivePort.listen((message) async {
+      print('Sender isolate: $message');
+      if (message is Map<String, dynamic>) {
+        try {
+          switch (message['type']) {
+            case PayjoinSenderRequestTypes.requestPosted:
+              //ToDo: Update frontend
+              return;
+            case PayjoinSenderRequestTypes.psbtToSign:
+              final proposalPsbt = message['psbt'] as String;
+              final utxos = _wallet.getUtxoWithPrivateKeys();
+              final finalizedPsbt = await _wallet.signPsbt(proposalPsbt, utxos);
+              _wallet.commitPsbt(finalizedPsbt);
+
+              //ToDo: Update frontend
+              _cleanupSession(pjUri);
+              await _payjoinStorage.markSenderSessionComplete(pjUri);
+              completer.complete();
+          }
+        } catch (e) {
+          _cleanupSession(pjUri);
+          await _payjoinStorage.markReceiverSessionUnrecoverable(pjUri);
+          completer.completeError(e);
+        }
+      } else if (message is PayjoinSessionError) {
+        _cleanupSession(pjUri);
+        if (message is UnrecoverableError) {
+          printV(message.message);
+          await _payjoinStorage.markReceiverSessionUnrecoverable(pjUri);
+        }
+        completer.completeError(message);
+      }
+    });
+
+    final args = [
+      receivePort.sendPort,
+      sender.toJson(),
+    ];
+
+    final isolate = await Isolate.spawn(
+      PayjoinSenderWorker.run,
+      args,
+    );
+
+    _activePollers[pjUri] = PayjoinPollerSession(isolate, receivePort);
+
+    return completer.future;
+  }
+
   Future<Receiver> initReceiver(String address,
       [bool isTestnet = false]) async {
     try {
-      final payjoinDirectory = await Url.fromStr(payjoinDirectoryUrl);
+      final payjoinDirectory =
+          await PayjoinUri.Url.fromStr(payjoinDirectoryUrl);
 
-      final ohttpKeys = await fetchOhttpKeys(
-        ohttpRelay: await _randomOhttpRelayUrl(),
+      final ohttpKeys = await PayjoinUri.fetchOhttpKeys(
+        ohttpRelay: await randomOhttpRelayUrl(),
         payjoinDirectory: payjoinDirectory,
       );
 
@@ -41,10 +158,10 @@ class PayjoinManager {
         network: isTestnet ? Network.testnet : Network.bitcoin,
         directory: payjoinDirectory,
         ohttpKeys: ohttpKeys,
-        ohttpRelay: await _randomOhttpRelayUrl(),
+        ohttpRelay: await randomOhttpRelayUrl(),
       );
     } catch (e) {
-      throw Exception('Error initializing payjoin Receiver: $e');
+      throw Exception('Error initializing Payjoin Receiver: $e');
     }
   }
 
@@ -115,18 +232,19 @@ class PayjoinManager {
               break;
 
             case PayjoinReceiverRequestTypes.proposalSent:
-              await _cleanupSession(receiver.id());
+              _cleanupSession(receiver.id());
               await _payjoinStorage.markReceiverSessionComplete(receiver.id());
               completer.complete();
           }
         } catch (e) {
-          await _cleanupSession(receiver.id());
+          _cleanupSession(receiver.id());
           await _payjoinStorage.markReceiverSessionUnrecoverable(receiver.id());
           completer.completeError(e);
         }
       } else if (message is PayjoinSessionError) {
-        await _cleanupSession(receiver.id());
+        _cleanupSession(receiver.id());
         if (message is UnrecoverableError) {
+          printV(message.message);
           await _payjoinStorage.markReceiverSessionUnrecoverable(receiver.id());
         }
         completer.completeError(message);
@@ -150,16 +268,16 @@ class PayjoinManager {
     return completer.future;
   }
 
+  void cleanupSessions() {
+    for (final sessionId in _activePollers.keys) {
+      _cleanupSession(sessionId);
+    }
+  }
 
-  Future<void> _cleanupSession(String sessionId) async {
+  void _cleanupSession(String sessionId) {
     _activePollers[sessionId]?.close();
     _activePollers.remove(sessionId);
   }
-
-  // Top-level function to generate random OHTTP relay URL
-  Future<Url> _randomOhttpRelayUrl() => Url.fromStr(
-        _ohttpRelayUrls[Random.secure().nextInt(_ohttpRelayUrls.length)],
-      );
 }
 
 class PayjoinPollerSession {
diff --git a/cw_bitcoin/lib/payjoin/payjoin_worker.dart b/cw_bitcoin/lib/payjoin/payjoin_receive_worker.dart
similarity index 93%
rename from cw_bitcoin/lib/payjoin/payjoin_worker.dart
rename to cw_bitcoin/lib/payjoin/payjoin_receive_worker.dart
index 74fd5a43a..819ed3166 100644
--- a/cw_bitcoin/lib/payjoin/payjoin_worker.dart
+++ b/cw_bitcoin/lib/payjoin/payjoin_receive_worker.dart
@@ -3,6 +3,7 @@ import 'dart:io';
 import 'dart:isolate';
 import 'dart:typed_data';
 
+import 'package:cw_bitcoin/payjoin/payjoin_session_errors.dart';
 import 'package:cw_bitcoin/psbt_signer.dart';
 import 'package:cw_core/utils/print_verbose.dart';
 import 'package:payjoin_flutter/bitcoin_ffi.dart';
@@ -19,23 +20,6 @@ enum PayjoinReceiverRequestTypes {
   processPsbt;
 }
 
-class PayjoinSessionError {
-  final String message;
-
-  const PayjoinSessionError._(this.message);
-
-  factory PayjoinSessionError.recoverable(String message) = RecoverableError;
-  factory PayjoinSessionError.unrecoverable(String message) = UnrecoverableError;
-}
-
-class RecoverableError extends PayjoinSessionError {
-  const RecoverableError(super.message) : super._();
-}
-
-class UnrecoverableError extends PayjoinSessionError {
-  const UnrecoverableError(super.message) : super._();
-}
-
 class PayjoinReceiverWorker {
   final SendPort sendPort;
   final pendingRequests = <String, Completer<dynamic>>{};
diff --git a/cw_bitcoin/lib/payjoin/payjoin_send_worker.dart b/cw_bitcoin/lib/payjoin/payjoin_send_worker.dart
new file mode 100644
index 000000000..9e0ef7a37
--- /dev/null
+++ b/cw_bitcoin/lib/payjoin/payjoin_send_worker.dart
@@ -0,0 +1,111 @@
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+
+import 'package:cw_bitcoin/payjoin/manager.dart';
+import 'package:cw_bitcoin/payjoin/payjoin_session_errors.dart';
+import 'package:payjoin_flutter/common.dart';
+import 'package:payjoin_flutter/send.dart';
+import 'package:payjoin_flutter/src/generated/frb_generated.dart' as pj;
+
+enum PayjoinSenderRequestTypes {
+  requestPosted,
+  psbtToSign;
+}
+
+class PayjoinSenderWorker {
+  final SendPort sendPort;
+  final pendingRequests = <String, Completer<dynamic>>{};
+
+  PayjoinSenderWorker._(this.sendPort);
+
+  static Future<void> run(List<Object> args) async {
+    await pj.core.init();
+
+    final sendPort = args[0] as SendPort;
+    final senderJson = args[1] as String;
+
+    final sender = Sender.fromJson(senderJson);
+    final worker = PayjoinSenderWorker._(sendPort);
+
+    try {
+      final proposalPsbt = await worker.runSender(sender);
+      sendPort.send({
+        'type': PayjoinSenderRequestTypes.psbtToSign,
+        'psbt': proposalPsbt,
+      });
+    } catch (e) {
+      sendPort.send(e);
+    }
+  }
+
+  /// Run a payjoin sender (V2 protocol first, fallback to V1).
+  Future<String> runSender(Sender sender) async {
+    final httpClient = HttpClient();
+
+    try {
+      return await _runSenderV2(sender, httpClient);
+    } catch (e) {
+      if (e is PayjoinException &&
+          // TODO condition on error type instead of message content
+          e.message?.contains('parse receiver public key') == true) {
+        return await _runSenderV1(sender, httpClient);
+      } else if (e is HttpException) {
+        throw Exception(PayjoinSessionError.recoverable(e.toString()));
+      } else {
+        throw Exception(PayjoinSessionError.unrecoverable(e.toString()));
+      }
+    }
+  }
+
+  /// Attempt to send payjoin using the V2 of the protocol.
+  Future<String> _runSenderV2(Sender sender, HttpClient httpClient) async {
+    final postRequest = await sender.extractV2(
+      ohttpProxyUrl: await await PayjoinManager.randomOhttpRelayUrl(),
+    );
+
+    final postResult = await _postRequest(httpClient, postRequest.$1);
+    final getContext =
+        await postRequest.$2.processResponse(response: postResult);
+
+    sendPort.send({'type': PayjoinSenderRequestTypes.requestPosted});
+
+    while (true) {
+      final getRequest = await getContext.extractReq(
+        ohttpRelay: await PayjoinManager.randomOhttpRelayUrl(),
+      );
+      final getRes = await _postRequest(httpClient, getRequest.$1);
+      final proposalPsbt = await getContext.processResponse(
+        response: getRes,
+        ohttpCtx: getRequest.$2,
+      );
+      if (proposalPsbt != null) return proposalPsbt;
+    }
+  }
+
+  /// Attempt to send payjoin using the V1 of the protocol.
+  Future<String> _runSenderV1(Sender sender, HttpClient httpClient) async {
+    try {
+      final postRequest = await sender.extractV1();
+      final response = await _postRequest(httpClient, postRequest.$1);
+
+      sendPort.send({'type': PayjoinSenderRequestTypes.requestPosted});
+
+      return await postRequest.$2.processResponse(response: response);
+    } catch (e) {
+      throw PayjoinSessionError.unrecoverable('Send V1 payjoin error: $e');
+    }
+  }
+
+  Future<List<int>> _postRequest(HttpClient client, Request req) async {
+    final httpRequest = await client.postUrl(Uri.parse(req.url.asString()));
+    httpRequest.headers.set('Content-Type', req.contentType);
+    httpRequest.add(req.body);
+
+    final response = await httpRequest.close();
+    return response.fold<List<int>>(
+      [],
+      (previous, element) => previous..addAll(element),
+    );
+  }
+}
diff --git a/cw_bitcoin/lib/payjoin/payjoin_session_errors.dart b/cw_bitcoin/lib/payjoin/payjoin_session_errors.dart
new file mode 100644
index 000000000..06e0a5431
--- /dev/null
+++ b/cw_bitcoin/lib/payjoin/payjoin_session_errors.dart
@@ -0,0 +1,16 @@
+class PayjoinSessionError {
+  final String message;
+
+  const PayjoinSessionError._(this.message);
+
+  factory PayjoinSessionError.recoverable(String message) = RecoverableError;
+  factory PayjoinSessionError.unrecoverable(String message) = UnrecoverableError;
+}
+
+class RecoverableError extends PayjoinSessionError {
+  const RecoverableError(super.message) : super._();
+}
+
+class UnrecoverableError extends PayjoinSessionError {
+  const UnrecoverableError(super.message) : super._();
+}
diff --git a/cw_bitcoin/lib/payjoin/storage.dart b/cw_bitcoin/lib/payjoin/storage.dart
index d88ba8516..6dc77a62a 100644
--- a/cw_bitcoin/lib/payjoin/storage.dart
+++ b/cw_bitcoin/lib/payjoin/storage.dart
@@ -1,194 +1,75 @@
 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({required Box<PayjoinSession> payjoinSessionSources})
-      : _payjoinSessionSources = payjoinSessionSources;
+  PayjoinStorage(this._payjoinSessionSources);
+
   final Box<PayjoinSession> _payjoinSessionSources;
 
-  static const String receiverPrefix = 'pj_recv_';
-  static const String senderPrefix = 'pj_send_';
+  static const String _receiverPrefix = 'pj_recv_';
+  static const String _senderPrefix = 'pj_send_';
 
   Future<void> insertReceiverSession(
     Receiver receiver,
     String walletId,
-  ) async {
-    final receiverSession =
-        PayjoinSession(walletId: walletId, receiver: receiver.toJson());
-
-    await _payjoinSessionSources.put(
-        "$receiverPrefix${receiver.id()}", receiverSession);
-  }
-
-// Future<(RecvSession?, Err?)> readReceiverSession(String sessionId) async {
-//   try {
-//     final (jsn, err) =
-//     await _hiveStorage.getValue(receiverPrefix + sessionId);
-//     if (err != null) throw err;
-//     final obj = jsonDecode(jsn!) as Map<String, dynamic>;
-//     final session = RecvSession.fromJson(obj);
-//     return (session, null);
-//   } catch (e) {
-//     return (
-//     null,
-//     Err(
-//       e.toString(),
-//       expected: e.toString() == 'No Receiver with id $sessionId',
-//     )
-//     );
-//   }
-// }
+  ) =>
+      _payjoinSessionSources.put(
+        "$_receiverPrefix${receiver.id()}",
+        PayjoinSession(
+          walletId: walletId,
+          receiver: receiver.toJson(),
+        ),
+      );
 
   Future<void> markReceiverSessionComplete(String sessionId) async {
-    final session =
-        await _payjoinSessionSources.get("$receiverPrefix${sessionId}")!;
+    final session = _payjoinSessionSources.get("$_receiverPrefix${sessionId}")!;
 
     session.status = "success";
     await session.save();
   }
 
   Future<void> markReceiverSessionUnrecoverable(String sessionId) async {
-    final session =
-        await _payjoinSessionSources.get("$receiverPrefix${sessionId}")!;
+    final session = _payjoinSessionSources.get("$_receiverPrefix${sessionId}")!;
 
     session.status = "unrecoverable";
     await session.save();
   }
 
-// Future<(List<RecvSession>, Err?)> readAllReceivers() async {
-//   //deleteAllSessions();
-//   try {
-//     final (allData, err) = await _hiveStorage.getAll();
-//     if (err != null) return (List<RecvSession>.empty(), err);
-//
-//     final List<RecvSession> receivers = [];
-//     allData!.forEach((key, value) {
-//       if (key.startsWith(receiverPrefix)) {
-//         try {
-//           final obj = jsonDecode(value) as Map<String, dynamic>;
-//           receivers.add(RecvSession.fromJson(obj));
-//         } catch (e) {
-//           // Skip invalid entries
-//           debugPrint('Error: $e');
-//         }
-//       }
-//     });
-//     return (receivers, null);
-//   } catch (e) {
-//     return (List<RecvSession>.empty(), Err(e.toString()));
-//   }
-// }
-//
-// Future<Err?> insertSenderSession(
-//     Sender sender,
-//     String pjUrl,
-//     String walletId,
-//     bool isTestnet,
-//     ) async {
-//   try {
-//     final sendSession = SendSession(
-//       isTestnet,
-//       sender,
-//       walletId,
-//       pjUrl,
-//       PayjoinSessionStatus.pending,
-//     );
-//
-//     await _hiveStorage.saveValue(
-//       key: senderPrefix + pjUrl,
-//       value: jsonEncode(sendSession.toJson()),
-//     );
-//     return null;
-//   } catch (e) {
-//     return Err(e.toString());
-//   }
-// }
-//
-// Future<(SendSession?, Err?)> readSenderSession(String pjUrl) async {
-//   try {
-//     final (jsn, err) = await _hiveStorage.getValue(senderPrefix + pjUrl);
-//     if (err != null) throw err;
-//     final obj = jsonDecode(jsn!) as Map<String, dynamic>;
-//     final session = SendSession.fromJson(obj);
-//     return (session, null);
-//   } catch (e) {
-//     return (
-//     null,
-//     Err(
-//       e.toString(),
-//       expected: e.toString() == 'No Sender with id $pjUrl',
-//     )
-//     );
-//   }
-// }
-//
-// Future<Err?> markSenderSessionComplete(String pjUrl) async {
-//   try {
-//     final (session, err) = await readSenderSession(pjUrl);
-//     if (err != null) return err;
-//
-//     final updatedSession = SendSession(
-//       session!.isTestnet,
-//       session.sender,
-//       session.walletId,
-//       session.pjUri,
-//       PayjoinSessionStatus.success,
-//     );
-//
-//     await _hiveStorage.saveValue(
-//       key: senderPrefix + pjUrl,
-//       value: jsonEncode(updatedSession.toJson()),
-//     );
-//     return null;
-//   } catch (e) {
-//     return Err(e.toString());
-//   }
-// }
-//
-// Future<Err?> markSenderSessionUnrecoverable(String pjUri) async {
-//   try {
-//     final (session, err) = await readSenderSession(pjUri);
-//     if (err != null) return err;
-//
-//     final updatedSession = SendSession(
-//       session!.isTestnet,
-//       session.sender,
-//       session.walletId,
-//       session.pjUri,
-//       PayjoinSessionStatus.unrecoverable,
-//     );
-//
-//     await _hiveStorage.saveValue(
-//       key: senderPrefix + pjUri,
-//       value: jsonEncode(updatedSession.toJson()),
-//     );
-//     return null;
-//   } catch (e) {
-//     return Err(e.toString());
-//   }
-// }
-//
-// Future<(List<SendSession>, Err?)> readAllSenders() async {
-//   try {
-//     final (allData, err) = await _hiveStorage.getAll();
-//     if (err != null) return (List<SendSession>.empty(), err);
-//
-//     final List<SendSession> senders = [];
-//     allData!.forEach((key, value) {
-//       if (key.startsWith(senderPrefix)) {
-//         try {
-//           final obj = jsonDecode(value) as Map<String, dynamic>;
-//           senders.add(SendSession.fromJson(obj));
-//         } catch (e) {
-//           // Skip invalid entries
-//           debugPrint('Error: $e');
-//         }
-//       }
-//     });
-//     return (senders, null);
-//   } catch (e) {
-//     return (List<SendSession>.empty(), Err(e.toString()));
-//   }
-// }
+  Future<void> insertSenderSession(
+    Sender sender,
+    String pjUrl,
+    String walletId,
+  ) =>
+      _payjoinSessionSources.put(
+        "$_senderPrefix$pjUrl",
+        PayjoinSession(
+          walletId: walletId,
+          pjUri: pjUrl,
+          sender: sender.toJson(),
+        ),
+      );
+
+  Future<void> markSenderSessionComplete(String pjUrl) async {
+    final session = _payjoinSessionSources.get("$_senderPrefix$pjUrl")!;
+
+    session.status = "success";
+    await session.save();
+  }
+
+  Future<void> markSenderSessionUnrecoverable(String pjUrl) async {
+    final session = _payjoinSessionSources.get("$_senderPrefix$pjUrl")!;
+
+    session.status = "unrecoverable";
+    await session.save();
+  }
+
+  List<PayjoinSession> readAllOpenSessions(String walletId) =>
+      _payjoinSessionSources.values
+          .where((session) =>
+              session.walletId == walletId &&
+              session.status != "success" &&
+              session.status != "unrecoverable")
+          .toList();
 }
diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart
index 411c7de16..6930524eb 100644
--- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart
+++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart
@@ -1,3 +1,4 @@
+import 'package:cw_bitcoin/electrum_wallet.dart';
 import 'package:grpc/grpc.dart';
 import 'package:cw_bitcoin/exceptions.dart';
 import 'package:bitcoin_base/bitcoin_base.dart';
@@ -25,6 +26,8 @@ class PendingBitcoinTransaction with PendingTransaction {
     this.hasTaprootInputs = false,
     this.isMweb = false,
     this.utxos = const [],
+    this.publicKeys,
+    this.commitOverride,
   }) : _listeners = <void Function(ElectrumTransactionInfo transaction)>[];
 
   final WalletType type;
@@ -43,6 +46,8 @@ class PendingBitcoinTransaction with PendingTransaction {
   String? idOverride;
   String? hexOverride;
   List<String>? outputAddresses;
+  final Map<String, PublicKeyWithDerivationPath>? publicKeys;
+  Future<void> Function()? commitOverride;
 
   @override
   String get id => idOverride ?? _tx.txId();
@@ -129,6 +134,10 @@ class PendingBitcoinTransaction with PendingTransaction {
 
   @override
   Future<void> commit() async {
+    if (commitOverride != null) {
+      return commitOverride?.call();
+    }
+
     if (isMweb) {
       await _ltcCommit();
     } else {
diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart
index e4b894c4a..864d41367 100644
--- a/lib/bitcoin/cw_bitcoin.dart
+++ b/lib/bitcoin/cw_bitcoin.dart
@@ -721,11 +721,20 @@ class CWBitcoin extends Bitcoin {
   }
 
   @override
-  String buildV2PjStr({
-    required Object receiverWallet
-  }) {
-    final wallet = receiverWallet as BitcoinWallet;
-    return (wallet.walletAddresses as BitcoinWalletAddresses).payjoinEndpoint ?? '';
+  String getPayjoinEndpoint(Object wallet) {
+    final _wallet = wallet as BitcoinWallet;
+    return (_wallet.walletAddresses as BitcoinWalletAddresses).payjoinEndpoint ?? '';
+  }
+
+  @override
+  void updatePayjoinState(Object wallet, bool value) {
+    final _wallet = wallet as ElectrumWallet;
+    if (value) {
+      (_wallet.walletAddresses as BitcoinWalletAddresses).initPayjoin();
+    } else {
+      (_wallet.walletAddresses as BitcoinWalletAddresses).payjoinManager.cleanupSessions();
+      (_wallet.walletAddresses as BitcoinWalletAddresses).currentPayjoinReceiver = null;
+    }
   }
 
   @override
@@ -755,12 +764,10 @@ class CWBitcoin extends Bitcoin {
   }
 
   @override
-  Future<PendingBitcoinTransaction> extractPjTx(
-      Object wallet, String psbtString, Object credentials) {
+  Future<PendingBitcoinTransaction> extractPjTx(Object wallet, String psbtString) {
     return payjoin.extractPjTx(
       wallet,
-      psbtString,
-      credentials
+      psbtString
     );
   }
 }
diff --git a/lib/reactions/on_current_wallet_change.dart b/lib/reactions/on_current_wallet_change.dart
index 3840b042e..c21b89564 100644
--- a/lib/reactions/on_current_wallet_change.dart
+++ b/lib/reactions/on_current_wallet_change.dart
@@ -1,3 +1,4 @@
+import 'package:cake_wallet/bitcoin/bitcoin.dart';
 import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
 import 'package:cake_wallet/entities/fiat_api_mode.dart';
 import 'package:cake_wallet/entities/update_haven_rate.dart';
@@ -74,6 +75,10 @@ void startCurrentWalletChangeReaction(
         _setAutoGenerateSubaddressStatus(wallet, settingsStore);
       }
 
+      if (wallet.type == WalletType.bitcoin) {
+        bitcoin!.updatePayjoinState(wallet, settingsStore.usePayjoin);
+      }
+
       await wallet.connectToNode(node: node);
       if (wallet.type == WalletType.nano || wallet.type == WalletType.banano) {
         final powNode = settingsStore.getCurrentPowNode(wallet.type);
diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart
index 16bd54a35..0d1ad7668 100644
--- a/lib/src/screens/settings/privacy_page.dart
+++ b/lib/src/screens/settings/privacy_page.dart
@@ -51,7 +51,7 @@ class PrivacyPage extends BasePage {
               ),
               if (_privacySettingsViewModel.canUsePayjoin)
                 SettingsSwitcherCell(
-                  title: 'Use Payjoin', // ToDo: localize
+                  title: S.of(context).use_payjoin,
                   value: _privacySettingsViewModel.usePayjoin,
                   onValueChange: (BuildContext _, bool value) {
                     _privacySettingsViewModel.setUsePayjoin(value);
diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart
index 6ecaebdc1..88b6f7bfb 100644
--- a/lib/view_model/send/send_view_model.dart
+++ b/lib/view_model/send/send_view_model.dart
@@ -395,7 +395,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
 
       if (wallet.isHardwareWallet) state = IsAwaitingDeviceResponseState();
 
-      pendingTransaction = await (pjUri != null ?  performPayjoinSend() : wallet.createTransaction(_credentials())); // ToDo: Remove move Payjoin into create tx
+      pendingTransaction = await wallet.createTransaction(_credentials());
 
       if (provider is ThorChainExchangeProvider) {
         final outputCount = pendingTransaction?.outputCount ?? 0;
@@ -850,10 +850,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
     }
 
     // If a proposal is received, finalize the payjoin
-    return bitcoin!.extractPjTx(
-      wallet,
-      psbt,
-      _credentials()
-    );
+    return bitcoin!.extractPjTx(wallet, psbt);
   }
 }
diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart
index 6ff0fb501..b9141af6f 100644
--- a/lib/view_model/settings/privacy_settings_view_model.dart
+++ b/lib/view_model/settings/privacy_settings_view_model.dart
@@ -172,5 +172,8 @@ abstract class PrivacySettingsViewModelBase with Store {
       _settingsStore.useMempoolFeeAPI = value;
 
   @action
-  void setUsePayjoin(bool value) => _settingsStore.usePayjoin = value;
+  void setUsePayjoin(bool value) {
+    _settingsStore.usePayjoin = value;
+    bitcoin!.updatePayjoinState(_wallet, value);
+  }
 }
diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart
index 94afe9e68..c66705d06 100644
--- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart
+++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart
@@ -284,7 +284,7 @@ abstract class WalletAddressListViewModelBase
       case WalletType.haven:
         return HavenURI(amount: amount, address: address.address);
       case WalletType.bitcoin:
-        final pjEndpoint = bitcoin!.buildV2PjStr(receiverWallet: wallet);
+        final pjEndpoint = bitcoin!.getPayjoinEndpoint(wallet);
         return BitcoinURI(amount: amount, address: address.address, pjUri: pjEndpoint);
       case WalletType.litecoin:
         return LitecoinURI(amount: amount, address: address.address);
diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb
index b0955b6d7..6e6bd130c 100644
--- a/res/values/strings_ar.arb
+++ b/res/values/strings_ar.arb
@@ -905,6 +905,7 @@
   "use": "التبديل إلى",
   "use_card_info_three": "استخدم البطاقة الرقمية عبر الإنترنت أو مع طرق الدفع غير التلامسية.",
   "use_card_info_two": "يتم تحويل الأموال إلى الدولار الأمريكي عند الاحتفاظ بها في الحساب المدفوع مسبقًا ، وليس بالعملات الرقمية.",
+  "use_payjoin": "يستخدم ٪٪٪",
   "use_ssl": "استخدم SSL",
   "use_suggested": "استخدام المقترح",
   "use_testnet": "استخدم testnet",
diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb
index e1fc3bd87..d42275e49 100644
--- a/res/values/strings_bg.arb
+++ b/res/values/strings_bg.arb
@@ -905,6 +905,7 @@
   "use": "Смяна на ",
   "use_card_info_three": "Използвайте дигиталната карта онлайн или чрез безконтактен метод на плащане.",
   "use_card_info_two": "Средствата се обръщат в USD, когато биват запазени в предплатената карта, а не в дигитална валута.",
+  "use_payjoin": "Използвайте %%",
   "use_ssl": "Използване на SSL",
   "use_suggested": "Използване на предложеното",
   "use_testnet": "Използвайте TestNet",
diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb
index 29c04496d..25797b255 100644
--- a/res/values/strings_cs.arb
+++ b/res/values/strings_cs.arb
@@ -905,6 +905,7 @@
   "use": "Přepnout na ",
   "use_card_info_three": "Použijte tuto digitální kartu online nebo bezkontaktními platebními metodami.",
   "use_card_info_two": "Prostředky jsou převedeny na USD, když jsou drženy na předplaceném účtu, nikoliv na digitální měnu.",
+  "use_payjoin": "Použijte %%TE",
   "use_ssl": "Použít SSL",
   "use_suggested": "Použít doporučený",
   "use_testnet": "Použijte testNet",
diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb
index 54c3a70e7..45ab89cbc 100644
--- a/res/values/strings_de.arb
+++ b/res/values/strings_de.arb
@@ -907,6 +907,7 @@
   "use": "Wechsel zu ",
   "use_card_info_three": "Verwenden Sie die digitale Karte online oder mit kontaktlosen Zahlungsmethoden.",
   "use_card_info_two": "Guthaben werden auf dem Prepaid-Konto in USD umgerechnet, nicht in digitale Währung.",
+  "use_payjoin": "Benutze Payjoin",
   "use_ssl": "SSL verwenden",
   "use_suggested": "Vorgeschlagen verwenden",
   "use_testnet": "TESTNET verwenden",
@@ -991,4 +992,4 @@
   "you_will_get": "Konvertieren zu",
   "you_will_send": "Konvertieren von",
   "yy": "YY"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb
index 995fb5595..d4532217d 100644
--- a/res/values/strings_en.arb
+++ b/res/values/strings_en.arb
@@ -905,6 +905,7 @@
   "use": "Switch to ",
   "use_card_info_three": "Use the digital card online or with contactless payment methods.",
   "use_card_info_two": "Funds are converted to USD when they're held in the prepaid account, not in digital currencies.",
+  "use_payjoin": "Use Payjoin",
   "use_ssl": "Use SSL",
   "use_suggested": "Use Suggested",
   "use_testnet": "Use Testnet",
@@ -988,4 +989,4 @@
   "you_will_get": "Convert to",
   "you_will_send": "Convert from",
   "yy": "YY"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb
index 011206fbf..a8d444733 100644
--- a/res/values/strings_es.arb
+++ b/res/values/strings_es.arb
@@ -906,6 +906,7 @@
   "use": "Utilizar a ",
   "use_card_info_three": "Utiliza la tarjeta digital en línea o con métodos de pago sin contacto.",
   "use_card_info_two": "Los fondos se convierten a USD cuando se mantienen en la cuenta prepaga, no en monedas digitales.",
+  "use_payjoin": "Usar Payjoin",
   "use_ssl": "Utiliza SSL",
   "use_suggested": "Usar sugerido",
   "use_testnet": "Usar TestNet",
@@ -989,4 +990,4 @@
   "you_will_get": "Convertir a",
   "you_will_send": "Convertir de",
   "yy": "YY"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb
index 7e2907c8f..8fed315af 100644
--- a/res/values/strings_fr.arb
+++ b/res/values/strings_fr.arb
@@ -905,6 +905,7 @@
   "use": "Changer vers code PIN à ",
   "use_card_info_three": "Utilisez la carte numérique en ligne ou avec des méthodes de paiement sans contact.",
   "use_card_info_two": "Les fonds sont convertis en USD lorsqu'ils sont détenus sur le compte prépayé, et non en devises numériques.",
+  "use_payjoin": "Utiliser Payjoin",
   "use_ssl": "Utiliser SSL",
   "use_suggested": "Suivre la suggestion",
   "use_testnet": "Utiliser TestNet",
@@ -988,4 +989,4 @@
   "you_will_get": "Convertir vers",
   "you_will_send": "Convertir depuis",
   "yy": "AA"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb
index d06210e3d..a41606d58 100644
--- a/res/values/strings_ha.arb
+++ b/res/values/strings_ha.arb
@@ -907,6 +907,7 @@
   "use": "Canja zuwa",
   "use_card_info_three": "Yi amfani da katin dijital akan layi ko tare da hanyoyin biyan kuɗi mara lamba.",
   "use_card_info_two": "Ana canza kuɗi zuwa dalar Amurka lokacin da ake riƙe su a cikin asusun da aka riga aka biya, ba cikin agogon dijital ba.",
+  "use_payjoin": "Yi amfani da %%",
   "use_ssl": "Yi amfani da SSL",
   "use_suggested": "Amfani da Shawarwari",
   "use_testnet": "Amfani da gwaji",
diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb
index 74de1126e..811fb57c7 100644
--- a/res/values/strings_hi.arb
+++ b/res/values/strings_hi.arb
@@ -907,6 +907,7 @@
   "use": "उपयोग ",
   "use_card_info_three": "डिजिटल कार्ड का ऑनलाइन या संपर्क रहित भुगतान विधियों के साथ उपयोग करें।",
   "use_card_info_two": "डिजिटल मुद्राओं में नहीं, प्रीपेड खाते में रखे जाने पर निधियों को यूएसडी में बदल दिया जाता है।",
+  "use_payjoin": "उपयोग %%%",
   "use_ssl": "उपयोग SSL",
   "use_suggested": "सुझाए गए का प्रयोग करें",
   "use_testnet": "टेस्टनेट का उपयोग करें",
diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb
index 41768bd4f..65f9720e7 100644
--- a/res/values/strings_hr.arb
+++ b/res/values/strings_hr.arb
@@ -905,6 +905,7 @@
   "use": "Prebaci na",
   "use_card_info_three": "Koristite digitalnu karticu online ili s beskontaktnim metodama plaćanja.",
   "use_card_info_two": "Sredstva se pretvaraju u USD kada se drže na prepaid računu, a ne u digitalnim valutama.",
+  "use_payjoin": "Koristite Payjoin",
   "use_ssl": "Koristi SSL",
   "use_suggested": "Koristite predloženo",
   "use_testnet": "Koristite TestNet",
@@ -988,4 +989,4 @@
   "you_will_get": "Razmijeni u",
   "you_will_send": "Razmijeni iz",
   "yy": "GG"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb
index 2a3aeed6d..a97e0c50d 100644
--- a/res/values/strings_hy.arb
+++ b/res/values/strings_hy.arb
@@ -905,6 +905,7 @@
   "use": "Փոխեք ",
   "use_card_info_three": "Օգտագործեք թվային քարտը առցանց կամ անշփման վճարման մեթոդներով։",
   "use_card_info_two": "Միջոցները փոխարկվում են ԱՄՆ դոլար երբ դրանք պահվում են կանխավճարային հաշվեկշռում, ոչ թե թվային արժույթներում։",
+  "use_payjoin": "Օգտագործեք Payjoin",
   "use_ssl": "Օգտագործել SSL",
   "use_suggested": "Օգտագործել առաջարկվածը",
   "use_testnet": "Օգտագործել Testnet",
@@ -988,4 +989,4 @@
   "you_will_get": "Ստացեք",
   "you_will_send": "Փոխանակեք",
   "yy": "ՏՏ"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb
index 90bf4d806..fe0af5afa 100644
--- a/res/values/strings_id.arb
+++ b/res/values/strings_id.arb
@@ -908,6 +908,7 @@
   "use": "Beralih ke ",
   "use_card_info_three": "Gunakan kartu digital secara online atau dengan metode pembayaran tanpa kontak.",
   "use_card_info_two": "Dana dikonversi ke USD ketika disimpan dalam akun pra-bayar, bukan dalam mata uang digital.",
+  "use_payjoin": "Menggunakan Payjoin",
   "use_ssl": "Gunakan SSL",
   "use_suggested": "Gunakan yang Disarankan",
   "use_testnet": "Gunakan TestNet",
@@ -991,4 +992,4 @@
   "you_will_get": "Konversi ke",
   "you_will_send": "Konversi dari",
   "yy": "YY"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb
index c3796be5a..332b4e9b7 100644
--- a/res/values/strings_it.arb
+++ b/res/values/strings_it.arb
@@ -907,6 +907,7 @@
   "use": "Passa a ",
   "use_card_info_three": "Utilizza la carta digitale online o con metodi di pagamento contactless.",
   "use_card_info_two": "I fondi vengono convertiti in USD quando sono detenuti nel conto prepagato, non in valute digitali.",
+  "use_payjoin": "Utilizzo Payjoin",
   "use_ssl": "Usa SSL",
   "use_suggested": "Usa suggerito",
   "use_testnet": "Usa TestNet",
@@ -991,4 +992,4 @@
   "you_will_get": "Converti a",
   "you_will_send": "Conveti da",
   "yy": "YY"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb
index 4ccd2d830..9fad19670 100644
--- a/res/values/strings_ja.arb
+++ b/res/values/strings_ja.arb
@@ -906,6 +906,7 @@
   "use": "使用する ",
   "use_card_info_three": "デジタルカードをオンラインまたは非接触型決済方法で使用してください。",
   "use_card_info_two": "デジタル通貨ではなく、プリペイドアカウントで保持されている場合、資金は米ドルに変換されます。",
+  "use_payjoin": "使用 %%%",
   "use_ssl": "SSLを使用する",
   "use_suggested": "推奨を使用",
   "use_testnet": "テストネットを使用します",
diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb
index 67a69e26b..88d9126d6 100644
--- a/res/values/strings_ko.arb
+++ b/res/values/strings_ko.arb
@@ -906,6 +906,7 @@
   "use": "사용하다 ",
   "use_card_info_three": "디지털 카드를 온라인 또는 비접촉식 결제 수단으로 사용하십시오.",
   "use_card_info_two": "디지털 화폐가 아닌 선불 계정에 보유하면 자금이 USD로 변환됩니다.",
+  "use_payjoin": "사용 Payjoin",
   "use_ssl": "SSL 사용",
   "use_suggested": "추천 사용",
   "use_testnet": "TestNet을 사용하십시오",
@@ -990,4 +991,4 @@
   "you_will_send": "다음에서 변환",
   "YY": "YY",
   "yy": "YY"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb
index dd2909d3f..d775d4b78 100644
--- a/res/values/strings_my.arb
+++ b/res/values/strings_my.arb
@@ -905,6 +905,7 @@
   "use": "သို့ပြောင်းပါ။",
   "use_card_info_three": "ဒစ်ဂျစ်တယ်ကတ်ကို အွန်လိုင်း သို့မဟုတ် ထိတွေ့မှုမဲ့ ငွေပေးချေမှုနည်းလမ်းများဖြင့် အသုံးပြုပါ။",
   "use_card_info_two": "ဒစ်ဂျစ်တယ်ငွေကြေးများဖြင့်မဟုတ်ဘဲ ကြိုတင်ငွေပေးချေသည့်အကောင့်တွင် သိမ်းထားသည့်အခါ ရန်ပုံငွေများကို USD သို့ ပြောင်းလဲပါသည်။",
+  "use_payjoin": "%% Chair ကိုအသုံးပြုပါ",
   "use_ssl": "SSL ကိုသုံးပါ။",
   "use_suggested": "အကြံပြုထားသည်ကို အသုံးပြုပါ။",
   "use_testnet": "testnet ကိုသုံးပါ",
diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb
index 8b32d669f..d8c86fb4a 100644
--- a/res/values/strings_nl.arb
+++ b/res/values/strings_nl.arb
@@ -905,6 +905,7 @@
   "use": "Gebruik ",
   "use_card_info_three": "Gebruik de digitale kaart online of met contactloze betaalmethoden.",
   "use_card_info_two": "Tegoeden worden omgezet naar USD wanneer ze op de prepaid-rekening staan, niet in digitale valuta.",
+  "use_payjoin": "Gebruik Payjoin",
   "use_ssl": "Gebruik SSL",
   "use_suggested": "Gebruik aanbevolen",
   "use_testnet": "Gebruik testnet",
@@ -989,4 +990,4 @@
   "you_will_get": "Converteren naar",
   "you_will_send": "Converteren van",
   "yy": "JJ"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb
index 2f2c19546..66d075a0b 100644
--- a/res/values/strings_pl.arb
+++ b/res/values/strings_pl.arb
@@ -905,6 +905,7 @@
   "use": "Użyj ",
   "use_card_info_three": "Użyj cyfrowej karty online lub za pomocą zbliżeniowych metod płatności.",
   "use_card_info_two": "Środki są przeliczane na USD, gdy są przechowywane na koncie przedpłaconym, a nie w walutach cyfrowych.",
+  "use_payjoin": "Używać Payjoin",
   "use_ssl": "Użyj SSL",
   "use_suggested": "Użyj sugerowane",
   "use_testnet": "Użyj testne",
@@ -988,4 +989,4 @@
   "you_will_get": "Konwertuj na",
   "you_will_send": "Konwertuj z",
   "yy": "RR"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb
index cf3adcf82..d6a157239 100644
--- a/res/values/strings_pt.arb
+++ b/res/values/strings_pt.arb
@@ -907,6 +907,7 @@
   "use": "Use PIN de ",
   "use_card_info_three": "Use o cartão digital online ou com métodos de pagamento sem contato.",
   "use_card_info_two": "Os fundos são convertidos para USD quando mantidos na conta pré-paga, não em moedas digitais.",
+  "use_payjoin": "Usar Payjoin",
   "use_ssl": "Use SSL",
   "use_suggested": "Uso sugerido",
   "use_testnet": "Use testNet",
@@ -991,4 +992,4 @@
   "you_will_get": "Converter para",
   "you_will_send": "Converter de",
   "yy": "aa"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb
index 0ba732a1c..992ad83cf 100644
--- a/res/values/strings_ru.arb
+++ b/res/values/strings_ru.arb
@@ -906,6 +906,7 @@
   "use": "Использовать ",
   "use_card_info_three": "Используйте цифровую карту онлайн или с помощью бесконтактных способов оплаты.",
   "use_card_info_two": "Средства конвертируются в доллары США, когда они хранятся на предоплаченном счете, а не в цифровых валютах.",
+  "use_payjoin": "Использовать %%%",
   "use_ssl": "Использовать SSL",
   "use_suggested": "Использовать предложенный",
   "use_testnet": "Используйте Testnet",
diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb
index 29764b302..aa1c8974a 100644
--- a/res/values/strings_th.arb
+++ b/res/values/strings_th.arb
@@ -905,6 +905,7 @@
   "use": "สลับไปที่ ",
   "use_card_info_three": "ใช้บัตรดิจิตอลออนไลน์หรือผ่านวิธีการชำระเงินแบบไม่ต้องใช้บัตรกระดาษ",
   "use_card_info_two": "เงินจะถูกแปลงค่าเป็นดอลลาร์สหรัฐเมื่อถือไว้ในบัญชีสำรองเงิน ไม่ใช่สกุลเงินดิจิตอล",
+  "use_payjoin": "ใช้ %%%",
   "use_ssl": "ใช้ SSL",
   "use_suggested": "ใช้ที่แนะนำ",
   "use_testnet": "ใช้ testnet",
diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb
index 772ed2cc0..96a78859c 100644
--- a/res/values/strings_tl.arb
+++ b/res/values/strings_tl.arb
@@ -905,6 +905,7 @@
   "use": "Lumipat sa ",
   "use_card_info_three": "Gamitin ang digital card online o sa mga paraan ng pagbabayad na walang contact.",
   "use_card_info_two": "Ang mga pondo ay na-convert sa USD kapag hawak sa prepaid account, hindi sa mga digital na pera.",
+  "use_payjoin": "Gumamit ng Payjoin",
   "use_ssl": "Gumamit ng SSL",
   "use_suggested": "Gumamit ng iminungkahing",
   "use_testnet": "Gumamit ng testnet",
@@ -988,4 +989,4 @@
   "you_will_get": "I-convert sa",
   "you_will_send": "I-convert mula sa",
   "yy": "YY"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb
index 34fc7da8c..16b37d733 100644
--- a/res/values/strings_tr.arb
+++ b/res/values/strings_tr.arb
@@ -905,6 +905,7 @@
   "use": "Şuna geç: ",
   "use_card_info_three": "Dijital kartı çevrimiçi olarak veya temassız ödeme yöntemleriyle kullanın.",
   "use_card_info_two": "Paralar, dijital para birimlerinde değil, ön ödemeli hesapta tutulduğunda USD'ye dönüştürülür.",
+  "use_payjoin": "Kullanmak Payjoin",
   "use_ssl": "SSL kullan",
   "use_suggested": "Önerileni Kullan",
   "use_testnet": "TestNet kullanın",
@@ -988,4 +989,4 @@
   "you_will_get": "Biçimine dönüştür:",
   "you_will_send": "Biçiminden dönüştür:",
   "yy": "YY"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb
index 35d12cbbb..3e0dee67d 100644
--- a/res/values/strings_uk.arb
+++ b/res/values/strings_uk.arb
@@ -906,6 +906,7 @@
   "use": "Використати ",
   "use_card_info_three": "Використовуйте цифрову картку онлайн або за допомогою безконтактних методів оплати.",
   "use_card_info_two": "Кошти конвертуються в долари США, якщо вони зберігаються на передплаченому рахунку, а не в цифрових валютах.",
+  "use_payjoin": "Використовуйте %%",
   "use_ssl": "Використати SSL",
   "use_suggested": "Використати запропоноване",
   "use_testnet": "Використовуйте тестову мережу",
diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb
index 874b9913e..b145f94b7 100644
--- a/res/values/strings_ur.arb
+++ b/res/values/strings_ur.arb
@@ -907,6 +907,7 @@
   "use": "تبدیل کرنا",
   "use_card_info_three": "ڈیجیٹل کارڈ آن لائن یا کنٹیکٹ لیس ادائیگی کے طریقوں کے ساتھ استعمال کریں۔",
   "use_card_info_two": "رقوم کو امریکی ڈالر میں تبدیل کیا جاتا ہے جب پری پیڈ اکاؤنٹ میں رکھا جاتا ہے، ڈیجیٹل کرنسیوں میں نہیں۔",
+  "use_payjoin": "٪٪٪ کا استعمال کریں",
   "use_ssl": "SSL استعمال کریں۔",
   "use_suggested": "تجویز کردہ استعمال کریں۔",
   "use_testnet": "ٹیسٹ نیٹ استعمال کریں",
diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb
index 5b3b08a6b..5aba4fef6 100644
--- a/res/values/strings_vi.arb
+++ b/res/values/strings_vi.arb
@@ -904,6 +904,7 @@
   "use": "Chuyển sang",
   "use_card_info_three": "Sử dụng thẻ kỹ thuật số trực tuyến hoặc với các phương thức thanh toán không tiếp xúc.",
   "use_card_info_two": "Các khoản tiền được chuyển đổi thành USD khi chúng được giữ trong tài khoản trả trước, không phải trong các loại tiền kỹ thuật số.",
+  "use_payjoin": "Sử dụng Payjoin",
   "use_ssl": "Sử dụng SSL",
   "use_suggested": "Sử dụng đề xuất",
   "use_testnet": "Sử dụng Testnet",
@@ -987,4 +988,4 @@
   "you_will_get": "Chuyển đổi thành",
   "you_will_send": "Chuyển đổi từ",
   "yy": "YY"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb
index 360676a7e..4401ae992 100644
--- a/res/values/strings_yo.arb
+++ b/res/values/strings_yo.arb
@@ -906,6 +906,7 @@
   "use": "Lo",
   "use_card_info_three": "Ẹ lo káàdí ayélujára lórí wẹ́ẹ̀bù tàbí ẹ lò ó lórí àwọn ẹ̀rọ̀ ìrajà tíwọn kò kò.",
   "use_card_info_two": "A pààrọ̀ owó sí owó Amẹ́ríkà tó bá wà nínú àkanti t'á ti fikún tẹ́lẹ̀tẹ́lẹ̀. A kò kó owó náà nínú owó ayélujára.",
+  "use_payjoin": "Lo %%",
   "use_ssl": "Lo SSL",
   "use_suggested": "Lo àbá",
   "use_testnet": "Lo tele",
diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb
index e032c40c4..ee698fdb8 100644
--- a/res/values/strings_zh.arb
+++ b/res/values/strings_zh.arb
@@ -905,6 +905,7 @@
   "use": "切换使用",
   "use_card_info_three": "在线使用电子卡或使用非接触式支付方式。",
   "use_card_info_two": "预付账户中的资金转换为美元,不是数字货币。",
+  "use_payjoin": "使用 %%%",
   "use_ssl": "使用SSL",
   "use_suggested": "使用建议",
   "use_testnet": "使用TestNet",
diff --git a/tool/configure.dart b/tool/configure.dart
index fa5d7da92..b9a72ad0b 100644
--- a/tool/configure.dart
+++ b/tool/configure.dart
@@ -240,11 +240,12 @@ abstract class Bitcoin {
   String? getUnusedMwebAddress(Object wallet);
   String? getUnusedSegwitAddress(Object wallet);
 
-  String buildV2PjStr({required Object receiverWallet});
+  void updatePayjoinState(Object wallet, bool state);
+  String getPayjoinEndpoint(Object wallet);
   Future<Sender> buildPayjoinRequest(String originalPsbt, dynamic pjUri, int fee);
   Future<String> buildOriginalPsbt(Object wallet, int fee, double amount, Object credentials);
   Future<String> requestAndPollV2Proposal(Sender sender);
-  Future<PendingBitcoinTransaction> extractPjTx(Object wallet, String psbtString, Object credentials);
+  Future<PendingBitcoinTransaction> extractPjTx(Object wallet, String psbtString);
 }
   """;