implement-payjoin (#1949)

* Initial Payjoin

* Initial Payjoin

* More payjoin stuff

* Minor fixes

* Minor fixes

* Minor cleanup

* Minor cleanup

* Minor cleanup

* Minor cleanup

* Minor cleanup

* Minor cleanup

* Fix minor bug causes by data inconsistency in the btc utxos

* Minor cleanup

* Minor cleanup

* Minor cleanup

* Minor cleanup

* Initial Payjoin

* Initial Payjoin

* More payjoin stuff

* Minor fixes

* Minor fixes

* Minor cleanup

* Minor cleanup

* Minor cleanup

* Minor cleanup

* Minor cleanup

* Minor cleanup

* Fix minor bug causes by data inconsistency in the btc utxos

* Minor cleanup

* Minor cleanup

* Minor cleanup

* Minor cleanup

* Fix Rebase issues

* Move PJ Receiver to isolate

* Add Payjoin Setting

* Payjoin Sender are now isolated

* Added Payjoin sessions to tx overview. Fix Fee issue with payjoin

* Clean up code

* Fix taproot for payjoin

* Fix CI Errors

* Add Payjoin UI elements and details page

* Add Payjoin UI elements and details page

* Fix Translations

* feat: Detect Payjoin URIs in pasted text and show to the User sending Payjoin

* feat: rename pjUri to payjoinURI for more code clarity

* Update res/values/strings_pl.arb

Co-authored-by: cyan <cyjan@mrcyjanek.net>

* Update cw_bitcoin/lib/payjoin/manager.dart

Co-authored-by: cyan <cyjan@mrcyjanek.net>

* Update cw_bitcoin/lib/payjoin/manager.dart

Co-authored-by: cyan <cyjan@mrcyjanek.net>

* feat: Disable Payjoin per default

* feat: Disable Payjoin fully if disabled or no Inputs available

* feat: Resume Payjoin if app comes back to foreground

* chore: Revert overly aggressive code formats

* feat: show correct Payjoin amount for receivers

* feat: Improved payjoin status

* feat: Show payjoin errors on payjoin details screen

* deps: update flutter to 3.27.4

* feat: Revert localisations

* bug: Remove duplicate transaction id on payjoin details

* style: remove double await in payjoin sender

* refactor(cw_bitcoin): Refactor method signatures and convert constructor to factory

* refactor(cw_bitcoin): Refactor wallet service and PSBT signer for cleaner code

Removed unnecessary `CakeHive` dependency and refactored `BitcoinWallet` initialization to use `payjoinSessionSource`. Improved code readability in `PsbtSigner` by reformatting lines and simplifying constructor methods for `UtxoWithPrivateKey`.

* fix: Resume Payjoin Sessions and load PJUri after sleep

* feat: Add "Copy Payjoin URL button" to receive screen

* fix: Add "Payjoin enabled"-Box below QR Code on the receive screen

* fix: Set payjoin_enabled color to black independent of the theme

* refactor: Payjoin session management and cleanup unused code.

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
Co-authored-by: cyan <cyjan@mrcyjanek.net>
This commit is contained in:
Konstantin Ullrich
2025-05-12 20:33:14 +03:00
committed by GitHub
co-authored by cyan Omar Hatem
parent 4a08e18f00
commit 82e3ebf4fa
84 changed files with 2622 additions and 198 deletions
+62 -20
View File
@@ -109,26 +109,29 @@ class CWBitcoin extends Bitcoin {
required TransactionPriority priority,
int? feeRate,
UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any,
String? payjoinUri,
}) {
final bitcoinFeeRate =
priority == BitcoinTransactionPriority.custom && feeRate != null ? feeRate : null;
priority == BitcoinTransactionPriority.custom && feeRate != null
? feeRate
: null;
return BitcoinTransactionCredentials(
outputs
.map((out) => OutputInfo(
fiatAmount: out.fiatAmount,
cryptoAmount: out.cryptoAmount,
address: out.address,
note: out.note,
sendAll: out.sendAll,
extractedAddress: out.extractedAddress,
isParsedAddress: out.isParsedAddress,
formattedCryptoAmount: out.formattedCryptoAmount,
memo: out.memo))
.toList(),
priority: priority as BitcoinTransactionPriority,
feeRate: bitcoinFeeRate,
coinTypeToSpendFrom: coinTypeToSpendFrom,
);
outputs
.map((out) => OutputInfo(
fiatAmount: out.fiatAmount,
cryptoAmount: out.cryptoAmount,
address: out.address,
note: out.note,
sendAll: out.sendAll,
extractedAddress: out.extractedAddress,
isParsedAddress: out.isParsedAddress,
formattedCryptoAmount: out.formattedCryptoAmount,
memo: out.memo))
.toList(),
priority: priority as BitcoinTransactionPriority,
feeRate: bitcoinFeeRate,
coinTypeToSpendFrom: coinTypeToSpendFrom,
payjoinUri: payjoinUri);
}
@override
@@ -224,9 +227,14 @@ class CWBitcoin extends Bitcoin {
await bitcoinWallet.updateAllUnspents();
}
WalletService createBitcoinWalletService(Box<WalletInfo> walletInfoSource,
Box<UnspentCoinsInfo> unspentCoinSource, bool alwaysScan, bool isDirect) {
return BitcoinWalletService(walletInfoSource, unspentCoinSource, alwaysScan, isDirect);
WalletService createBitcoinWalletService(
Box<WalletInfo> walletInfoSource,
Box<UnspentCoinsInfo> unspentCoinSource,
Box<PayjoinSession> payjoinSessionSource,
bool alwaysScan,
bool isDirect) {
return BitcoinWalletService(walletInfoSource, unspentCoinSource,
payjoinSessionSource, alwaysScan, isDirect);
}
WalletService createLitecoinWalletService(Box<WalletInfo> walletInfoSource,
@@ -550,6 +558,10 @@ class CWBitcoin extends Bitcoin {
return option is BitcoinReceivePageOption;
}
@override
bool isPayjoinAvailable(Object wallet) =>
(wallet is BitcoinWallet) && (wallet as BitcoinWallet).isPayjoinAvailable;
@override
BitcoinAddressType getOptionToType(ReceivePageOption option) {
return (option as BitcoinReceivePageOption).toType();
@@ -706,4 +718,34 @@ class CWBitcoin extends Bitcoin {
return null;
}
}
@override
String getPayjoinEndpoint(Object wallet) {
final _wallet = wallet as ElectrumWallet;
if (!isPayjoinAvailable(wallet)) return '';
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 {
stopPayjoinSessions(wallet);
}
}
@override
void resumePayjoinSessions(Object wallet) {
final _wallet = wallet as ElectrumWallet;
(_wallet.walletAddresses as BitcoinWalletAddresses).initPayjoin();
}
@override
void stopPayjoinSessions(Object wallet) {
final _wallet = wallet as ElectrumWallet;
(_wallet.walletAddresses as BitcoinWalletAddresses).payjoinManager.cleanupSessions();
(_wallet.walletAddresses as BitcoinWalletAddresses).currentPayjoinReceiver = null;
}
}