From d2ed3315d34ad26ee932e45d97053d9d2a71c75c Mon Sep 17 00:00:00 2001 From: kumulynja Date: Wed, 19 Jun 2024 22:06:59 +0200 Subject: [PATCH 1/7] fix return value of assumeInteractiveReceiver to MaybeInputsOwned --- lib/receive/v1.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/receive/v1.dart b/lib/receive/v1.dart index d436f85..6e84570 100644 --- a/lib/receive/v1.dart +++ b/lib/receive/v1.dart @@ -56,7 +56,7 @@ class UncheckedProposal extends receive.UncheckedProposal { ///Call this method if the only way to initiate a Payjoin with this receiver requires manual intervention, as in most consumer wallets. /// So-called “non-interactive” receivers, like payment processors, /// that allow arbitrary requests are otherwise vulnerable to probing attacks. Those receivers call gettransactiontocheckbroadcast() and attesttestedandscheduledbroadcast() after making those checks downstream - Future assumeInteractiveReceiver() async { + Future assumeInteractiveReceiver() async { try { final res = await receive.UncheckedProposal.assumeInteractiveReceiver(ptr: this); From a4b5bc66a37968a567e35c568b038b7eca7a598a Mon Sep 17 00:00:00 2001 From: kumulynja Date: Fri, 21 Jun 2024 21:32:36 +0200 Subject: [PATCH 2/7] working version --- example/lib/bdk_client.dart | 2 -- example/lib/main.dart | 25 +++++++++++++++++-------- example/pubspec.lock | 12 +++++++----- example/pubspec.yaml | 13 +++++++------ lib/receive/v1.dart | 2 ++ 5 files changed, 33 insertions(+), 21 deletions(-) diff --git a/example/lib/bdk_client.dart b/example/lib/bdk_client.dart index acdd951..87c014c 100644 --- a/example/lib/bdk_client.dart +++ b/example/lib/bdk_client.dart @@ -82,8 +82,6 @@ class BdkClient { Future getBalance() async { final balance = await wallet.getBalance(); - final res = "Total Balance: ${balance.total.toString()}"; - debugPrint(res); return balance.total; } diff --git a/example/lib/main.dart b/example/lib/main.dart index 386d585..5ae3377 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -112,6 +112,8 @@ class _PayJoinState extends State { setState(() { displayText = "sync complete"; }); + debugPrint( + "receiver balance: ${(await receiver.getBalance()).toString()}"); debugPrint( "sender balance: ${(await sender.getBalance()).toString()}"); }, @@ -126,7 +128,7 @@ class _PayJoinState extends State { onPressed: () async { final address = (await receiver.getNewAddress()).address; final res = await payJoinLibrary.buildPjUri( - 0.0083285, await address.toQrUri()); + 0.00008328, await address.toQrUri()); setState(() { pjUri = res; displayText = res; @@ -164,13 +166,16 @@ class _PayJoinState extends State { )), TextButton( onPressed: () async { - final (provisionalProposal, contextV1) = await payJoinLibrary - .handlePjRequest(await senderPsbt.serialize(), pjUri, - (e) async { - final script = ScriptBuf(bytes: e); + final (provisionalProposal, contextV1) = + await payJoinLibrary.handlePjRequest( + await senderPsbt.serialize(), + pjUri, + (e) async { + final script = ScriptBuf(bytes: e); - return (await receiver.getAddressInfo(script)); - }); + return (await receiver.getAddressInfo(script)); + }, + ); final unspent = await receiver.listUnspent(); // Select receiver payjoin inputs. Map candidateInputs = { @@ -183,7 +188,7 @@ class _PayJoinState extends State { .tryPreservingPrivacy(candidateInputs: candidateInputs); var selectedUtxo = unspent.firstWhere( (i) => - i.outpoint.txid.toString() == selectedOutpoint.txid && + i.outpoint.txid == selectedOutpoint.txid && i.outpoint.vout == selectedOutpoint.vout, orElse: () => throw Exception('UTXO not found')); var txoToContribute = common.TxOut( @@ -215,6 +220,8 @@ class _PayJoinState extends State { final senderProcessedPsbt = (await sender.signPsbt( await PartiallySignedTransaction.fromString( receiverProcessedPsbt))); + debugPrint( + "\nProcessed and finalized sender psbt: ${await senderProcessedPsbt.serialize()}"); setState(() { processedAndFinalizedPsbt = senderProcessedPsbt; }); @@ -228,6 +235,8 @@ class _PayJoinState extends State { )), TextButton( onPressed: () async { + debugPrint( + 'Processed and finalized sender psbt: ${await processedAndFinalizedPsbt.serialize()}'); final res = await sender.broadcastPsbt(processedAndFinalizedPsbt); debugPrint("Broadcast success: $res"); diff --git a/example/pubspec.lock b/example/pubspec.lock index 8c706bb..a9ca1bc 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -37,8 +37,8 @@ packages: dependency: "direct main" description: path: "." - ref: "v0.31.2-dev.2" - resolved-ref: "18649436038282f379e9a4679656bcd084434ddd" + ref: bdk-payjoin-integration-fix + resolved-ref: ea7f666e1358bccb3fe6a99883d454bfcacf37f4 url: "https://github.com/LtbLightning/bdk-flutter" source: git version: "0.31.2-dev.2" @@ -422,9 +422,11 @@ packages: payjoin_flutter: dependency: "direct main" description: - path: ".." - relative: true - source: path + path: "." + ref: main + resolved-ref: c3d300fcf942cf0e5d42a093af416ac70777a69a + url: "https://github.com/LtbLightning/payjoin-flutter" + source: git version: "0.13.0" platform: dependency: transitive diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 50cf8ef..ad5c343 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -2,7 +2,7 @@ name: payjoin_flutter_example description: "Demonstrates how to use the payjoin plugin." # The following line prevents the package from being accidentally published to # pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev +publish_to: "none" # Remove this line if you wish to publish to pub.dev # The following defines the version and build number for your application. # A version number is three numbers separated by dots, like 1.2.43 @@ -19,7 +19,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: '>=3.2.3 <4.0.0' + sdk: ">=3.2.3 <4.0.0" # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -36,7 +36,9 @@ dependencies: # See https://dart.dev/tools/pub/dependencies#version-constraints # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. - path: ../ + git: + url: https://github.com/LtbLightning/payjoin-flutter + ref: main # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. @@ -45,8 +47,7 @@ dependencies: bdk_flutter: git: url: https://github.com/LtbLightning/bdk-flutter - ref: v0.31.2-dev.2 - + ref: bdk-payjoin-integration-fix google_fonts: ^6.2.1 @@ -60,4 +61,4 @@ dev_dependencies: flutter_lints: ^2.0.0 flutter: - uses-material-design: true \ No newline at end of file + uses-material-design: true diff --git a/lib/receive/v1.dart b/lib/receive/v1.dart index d436f85..284fd03 100644 --- a/lib/receive/v1.dart +++ b/lib/receive/v1.dart @@ -169,6 +169,8 @@ class ProvisionalProposal extends receive.ProvisionalProposal { return super.tryPreservingPrivacy(candidateInputs: candidateInputs); } on error.PayjoinError catch (e) { throw mapPayjoinError(e); + } catch (e) { + throw e; } } From de23573baddef65944dacc18d9121770c7230534 Mon Sep 17 00:00:00 2001 From: kumulynja Date: Sat, 22 Jun 2024 01:02:53 +0200 Subject: [PATCH 3/7] Separate steps for receiver and sender --- example/lib/main.dart | 92 ++++++++++++++++++-------------- example/lib/payjoin_library.dart | 25 +++------ 2 files changed, 59 insertions(+), 58 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 5ae3377..676eb02 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -4,6 +4,7 @@ import 'package:bdk_flutter/bdk_flutter.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:payjoin_flutter/common.dart' as common; +import 'package:payjoin_flutter/send.dart'; import 'package:payjoin_flutter/uri.dart' as pay_join_uri; import 'package:payjoin_flutter_example/bdk_client.dart'; import 'package:payjoin_flutter_example/payjoin_library.dart'; @@ -50,7 +51,9 @@ class _PayJoinState extends State { String displayText = ""; String pjUri = ""; late PartiallySignedTransaction senderPsbt; - late PartiallySignedTransaction processedAndFinalizedPsbt; + late String receiverPsbt; + late ContextV1 contextV1; + @override void initState() { sender.restoreWallet(); @@ -142,34 +145,44 @@ class _PayJoinState extends State { fontWeight: FontWeight.w800), )), TextButton( - onPressed: () async { - final balance = await sender.getBalance(); - debugPrint("Sender Balance: ${balance.toString()}"); - final uri = await pay_join_uri.Uri.fromString(pjUri); - final address = await uri.address(); - int amount = - (((await uri.amount()) ?? 0) * 100000000).toInt(); - final psbt = (await sender.createPsbt(address, amount, 2000)); - debugPrint( - "\nOriginal sender psbt: ${await psbt.serialize()}", - ); - setState(() { - senderPsbt = psbt; - }); - }, - child: Text( - "Create Sender psbt using receiver pjUri", - style: GoogleFonts.manrope( - color: Colors.black, - fontSize: 14, - fontWeight: FontWeight.w800), - )), + onPressed: () async { + final balance = await sender.getBalance(); + debugPrint("Sender Balance: ${balance.toString()}"); + final uri = await pay_join_uri.Uri.fromString(pjUri); + final address = await uri.address(); + int amount = (((await uri.amount()) ?? 0) * 100000000).toInt(); + final psbt = (await sender.createPsbt(address, amount, 2000)); + debugPrint( + "\nOriginal sender psbt: ${await psbt.serialize()}", + ); + + final requestContext = + (await (await RequestBuilder.fromPsbtAndUri( + psbtBase64: await psbt.serialize(), uri: uri)) + .buildRecommended(minFeeRate: 0)); + // In a real scenario, the sender would send the request to + // the payjoin endpoint of the receiver, here we just keep + // the context for the last step. + final (_, ctx) = await requestContext.extractContextV1(); + + setState(() { + senderPsbt = psbt; + contextV1 = ctx; + }); + }, + child: Text( + "Create Sender request psbt using receiver pjUri", + style: GoogleFonts.manrope( + color: Colors.black, + fontSize: 14, + fontWeight: FontWeight.w800), + ), + ), TextButton( onPressed: () async { - final (provisionalProposal, contextV1) = + final provisionalProposal = await payJoinLibrary.handlePjRequest( await senderPsbt.serialize(), - pjUri, (e) async { final script = ScriptBuf(bytes: e); @@ -208,26 +221,19 @@ class _PayJoinState extends State { address: await newReceiverAddress.address.asString()); final payJoinProposal = await provisionalProposal .finalizeProposal(processPsbt: (e) async { - debugPrint("\n Original receiver unsigned psbt: $e"); + debugPrint("\n Receiver response unsigned psbt: $e"); return await (await receiver.signPsbt( await PartiallySignedTransaction.fromString(e))) .serialize(); }); - final receiverPsbt = await payJoinProposal.psbt(); - debugPrint("\n Original receiver psbt: $receiverPsbt"); - final receiverProcessedPsbt = await contextV1.processResponse( - response: utf8.encode(receiverPsbt)); - final senderProcessedPsbt = (await sender.signPsbt( - await PartiallySignedTransaction.fromString( - receiverProcessedPsbt))); - debugPrint( - "\nProcessed and finalized sender psbt: ${await senderProcessedPsbt.serialize()}"); + receiverPsbt = await payJoinProposal.psbt(); + debugPrint("\n Receiver response psbt: $receiverPsbt"); setState(() { - processedAndFinalizedPsbt = senderProcessedPsbt; + receiverPsbt = receiverPsbt; }); }, child: Text( - "Process and finalize receiver Pj request", + "Create Receiver response psbt", style: GoogleFonts.manrope( color: Colors.black, fontSize: 14, @@ -235,14 +241,18 @@ class _PayJoinState extends State { )), TextButton( onPressed: () async { + final processedReceiverResponsePsbt = await contextV1 + .processResponse(response: utf8.encode(receiverPsbt)); + final finalizedPsbt = (await sender.signPsbt( + await PartiallySignedTransaction.fromString( + processedReceiverResponsePsbt))); debugPrint( - 'Processed and finalized sender psbt: ${await processedAndFinalizedPsbt.serialize()}'); - final res = - await sender.broadcastPsbt(processedAndFinalizedPsbt); + 'Processed and finalized sender psbt: ${await finalizedPsbt.serialize()}'); + final res = await sender.broadcastPsbt(finalizedPsbt); debugPrint("Broadcast success: $res"); }, child: Text( - "Broadcast processed psbt", + "Process response and broadcast final Sender psbt", style: GoogleFonts.manrope( color: Colors.black, fontSize: 14, diff --git a/example/lib/payjoin_library.dart b/example/lib/payjoin_library.dart index d4717b4..d8a6a14 100644 --- a/example/lib/payjoin_library.dart +++ b/example/lib/payjoin_library.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:typed_data'; import 'package:flutter/cupertino.dart'; @@ -22,28 +23,18 @@ class PayJoinLibrary { } } - Future<(v1.ProvisionalProposal, send.ContextV1)> handlePjRequest( - String psbtBase64, - String uriStr, - Future Function(Uint8List) isOwned) async { - final uri = await pj_uri.Uri.fromString(uriStr); - final (req, cxt) = await (await (await send.RequestBuilder.fromPsbtAndUri( - psbtBase64: psbtBase64, uri: uri)) - .buildWithAdditionalFee( - maxFeeContribution: 10000, - minFeeRate: 0, - clampFeeContribution: false)) - .extractContextV1(); + Future handlePjRequest( + String psbtBase64, Future Function(Uint8List) isOwned) async { + final body = utf8.encode(psbtBase64); + final headers = common.Headers(map: { 'content-type': 'text/plain', - 'content-length': req.body.length.toString(), + 'content-length': body.length.toString(), }); final unchecked = await v1.UncheckedProposal.fromRequest( - body: req.body.toList(), - query: (await req.url.query())!, - headers: headers); + body: body.toList(), query: '', headers: headers); final provisionalProposal = await handleUnckedProposal(unchecked, isOwned); - return (provisionalProposal, cxt); + return provisionalProposal; } Future handleUnckedProposal( From c4f820b920435da1b3877519ed7a7a7ed57bd401 Mon Sep 17 00:00:00 2001 From: kumulynja Date: Sat, 22 Jun 2024 01:37:09 +0200 Subject: [PATCH 4/7] fix integration test + bdk and payjoin dependencies in example --- .../bitcoin_core_full_cycle_test.dart | 9 +++++++-- example/lib/main.dart | 11 ++++++----- example/pubspec.lock | 12 +++++------- example/pubspec.yaml | 6 ++---- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/example/integration_test/bitcoin_core_full_cycle_test.dart b/example/integration_test/bitcoin_core_full_cycle_test.dart index 7998da6..55a1954 100644 --- a/example/integration_test/bitcoin_core_full_cycle_test.dart +++ b/example/integration_test/bitcoin_core_full_cycle_test.dart @@ -5,6 +5,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; import 'package:payjoin_flutter/common.dart' as common; +import 'package:payjoin_flutter/send.dart'; import 'package:payjoin_flutter/uri.dart' as pay_join_uri; import 'package:payjoin_flutter_example/btc_client.dart'; import 'package:payjoin_flutter_example/payjoin_library.dart'; @@ -35,11 +36,15 @@ void main() { final amount = await uri.amount(); final senderPsbt = (await sender.walletCreateFundedPsbt(amount, address, 2000))["psbt"]; + final requestContext = await (await RequestBuilder.fromPsbtAndUri( + psbtBase64: senderPsbt, uri: uri)) + .buildRecommended(minFeeRate: 0); + final (_, ctx) = await requestContext.extractContextV1(); debugPrint( "\nOriginal sender psbt: $senderPsbt", ); - final (provisionalProposal, ctx) = - await payJoinLib.handlePjRequest(senderPsbt, pjUri, (e) async { + final provisionalProposal = + await payJoinLib.handlePjRequest(senderPsbt, (e) async { final script = ScriptBuf(bytes: e); final address = await (await Address.fromScript( script: script, network: Network.regtest)) diff --git a/example/lib/main.dart b/example/lib/main.dart index 676eb02..b813009 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -51,7 +51,7 @@ class _PayJoinState extends State { String displayText = ""; String pjUri = ""; late PartiallySignedTransaction senderPsbt; - late String receiverPsbt; + late String receiverPsbtBase64; late ContextV1 contextV1; @override @@ -226,10 +226,10 @@ class _PayJoinState extends State { await PartiallySignedTransaction.fromString(e))) .serialize(); }); - receiverPsbt = await payJoinProposal.psbt(); + final receiverPsbt = await payJoinProposal.psbt(); debugPrint("\n Receiver response psbt: $receiverPsbt"); setState(() { - receiverPsbt = receiverPsbt; + receiverPsbtBase64 = receiverPsbt; }); }, child: Text( @@ -241,8 +241,9 @@ class _PayJoinState extends State { )), TextButton( onPressed: () async { - final processedReceiverResponsePsbt = await contextV1 - .processResponse(response: utf8.encode(receiverPsbt)); + final processedReceiverResponsePsbt = + await contextV1.processResponse( + response: utf8.encode(receiverPsbtBase64)); final finalizedPsbt = (await sender.signPsbt( await PartiallySignedTransaction.fromString( processedReceiverResponsePsbt))); diff --git a/example/pubspec.lock b/example/pubspec.lock index a9ca1bc..eda56e4 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -37,8 +37,8 @@ packages: dependency: "direct main" description: path: "." - ref: bdk-payjoin-integration-fix - resolved-ref: ea7f666e1358bccb3fe6a99883d454bfcacf37f4 + ref: main + resolved-ref: "821fe90d20c955e3cdfbfecea3b91fe24885552a" url: "https://github.com/LtbLightning/bdk-flutter" source: git version: "0.31.2-dev.2" @@ -422,11 +422,9 @@ packages: payjoin_flutter: dependency: "direct main" description: - path: "." - ref: main - resolved-ref: c3d300fcf942cf0e5d42a093af416ac70777a69a - url: "https://github.com/LtbLightning/payjoin-flutter" - source: git + path: ".." + relative: true + source: path version: "0.13.0" platform: dependency: transitive diff --git a/example/pubspec.yaml b/example/pubspec.yaml index ad5c343..77cf38a 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -36,9 +36,7 @@ dependencies: # See https://dart.dev/tools/pub/dependencies#version-constraints # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. - git: - url: https://github.com/LtbLightning/payjoin-flutter - ref: main + path: ../ # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. @@ -47,7 +45,7 @@ dependencies: bdk_flutter: git: url: https://github.com/LtbLightning/bdk-flutter - ref: bdk-payjoin-integration-fix + ref: main google_fonts: ^6.2.1 From 3bae24edb939a2e9a006bd3d8f33cd04dde57c19 Mon Sep 17 00:00:00 2001 From: kumulynja Date: Sat, 22 Jun 2024 01:38:30 +0200 Subject: [PATCH 5/7] set back bigger amount to transfer --- example/lib/main.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index b813009..87f8c6a 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -131,7 +131,7 @@ class _PayJoinState extends State { onPressed: () async { final address = (await receiver.getNewAddress()).address; final res = await payJoinLibrary.buildPjUri( - 0.00008328, await address.toQrUri()); + 0.0083285, await address.toQrUri()); setState(() { pjUri = res; displayText = res; From 2a80763021f963cc4bbcc5757bd1da73b81b64c0 Mon Sep 17 00:00:00 2001 From: kumulynja Date: Mon, 24 Jun 2024 17:11:14 +0200 Subject: [PATCH 6/7] use assumeInteractiveReceiver + add comments for non-interactive use --- example/lib/payjoin_library.dart | 40 +++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/example/lib/payjoin_library.dart b/example/lib/payjoin_library.dart index d8a6a14..8b37344 100644 --- a/example/lib/payjoin_library.dart +++ b/example/lib/payjoin_library.dart @@ -5,6 +5,7 @@ import 'dart:typed_data'; import 'package:flutter/cupertino.dart'; import 'package:payjoin_flutter/common.dart' as common; import 'package:payjoin_flutter/receive/v1.dart' as v1; +import 'package:payjoin_flutter/receive/v2.dart'; import 'package:payjoin_flutter/send.dart' as send; import 'package:payjoin_flutter/uri.dart' as pj_uri; @@ -33,19 +34,42 @@ class PayJoinLibrary { }); final unchecked = await v1.UncheckedProposal.fromRequest( body: body.toList(), query: '', headers: headers); - final provisionalProposal = await handleUnckedProposal(unchecked, isOwned); + final provisionalProposal = + await handleUncheckedProposal(unchecked, isOwned); return provisionalProposal; } - Future handleUnckedProposal( + Future handleUncheckedProposal( v1.UncheckedProposal uncheckedProposal, Future Function(Uint8List) isOwned) async { - // in a payment processor where the sender could go offline, this is where you schedule to broadcast the original_tx - var _ = await uncheckedProposal.extractTxToScheduleBroadcast(); - final inputsOwned = await uncheckedProposal.checkBroadcastSuitability( - canBroadcast: (e) async { - return true; - }); + // A consumer wallet has some manual interaction to initiate a payjoin, it + // is not a server that can receive a lot of requests without the user + // being aware of it. Therefore we say a consumer wallet app is an + // interactive receiver and an automatic payment processor is + // non-interactive. + // + // The way to check a proposal for these cases are different: + // - For an interactive receiver, you can just call + // `assumeInteractiveReceiver` as used here in the example code. + // - For a non-interactive receiver, you would extract the original tx + // with `extractTxToScheduleBroadcast` and check if it can be + // broadcasted in `checkBroadcastSuitability`. This way, if the sender + // doesn't complete the payjoin, you can still broadcast the original + // tx and get your funds. This protects against sender maliciousness of + // probing your utxo set amongst other things. + + final inputsOwned = await uncheckedProposal.assumeInteractiveReceiver(); + /* + // Non-interactive receiver example code: + final originalTx = await uncheckedProposal.extractTxToScheduleBroadcast(); + final inputsOwned = await uncheckedProposal.checkBroadcastSuitability( + canBroadcast: (e) async { + // Here you would check if the original tx is a valid tx that pays you + // and that can be broadcasted. + return true; + }); + */ + // Receive Check 2: receiver can't sign for proposal inputs final mixedInputScripts = await inputsOwned.checkInputsNotOwned(isOwned: isOwned); From e6a5eeeb0d4ac2dafe877197982368037498cec7 Mon Sep 17 00:00:00 2001 From: kumulynja Date: Mon, 24 Jun 2024 18:20:46 +0200 Subject: [PATCH 7/7] update changelog with 0.13.0-dev.2 version --- CHANGELOG.md | 70 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 709c28b..e71f72b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,33 +1,47 @@ +## [0.13.0-dev.2] + +### Fixed + +- Fix `assumeInteractiveReceiver` return type + +### Refactor + +- Separate receiver and sender logic in example app. + ## [0.13.0] ### Features & Modules + #### Send module -- ##### V1 - - `RequestBuilder` exposes `fromPsbtAndUri`, `buildWithAdditionalFee`, `buildRecommended`, `buildNonIncentivizing`, `alwaysDisableOutputSubstitution`. - - `RequestContext` exposes `extractContextV1` & `extractContextV2`. - - `ContextV1` exposes `processResponse`. -- ##### V2 - - `ContextV2` exposes `processResponse`. + +- ##### V1 + - `RequestBuilder` exposes `fromPsbtAndUri`, `buildWithAdditionalFee`, `buildRecommended`, `buildNonIncentivizing`, `alwaysDisableOutputSubstitution`. + - `RequestContext` exposes `extractContextV1` & `extractContextV2`. + - `ContextV1` exposes `processResponse`. +- ##### V2 + - `ContextV2` exposes `processResponse`. + #### Receive module -- ##### V1 - - `UncheckedProposal` exposes `fromRequest`, `extractTxToScheduleBroadcast`, `checkBroadcastSuitability`, `buildNonIncentivizing`, - `assumeInteractiveReceiver` &`alwaysDisableOutputSubstitution`. - - `MaybeInputsOwned` exposes `checkInputsNotOwned`. - - `MaybeMixedInputScripts` exposes `checkNoMixedInputScripts`. - - `MaybeInputsSeen` exposes `checkNoInputsSeenBefore`. - - `OutputsUnknown` exposes `identifyReceiverOutputs`. - - `ProvisionalProposal` exposes `substituteOutputAddress`, `contributeNonWitnessInput`, `contributeWitnessInput`, `tryPreservingPrivacy` & - `finalizeProposal`. - - `PayjoinProposal` exposes `isOutputSubstitutionDisabled`, `ownedVouts`, `psbt` & `utxosToBeLocked`. -- ##### V2 - - `Enroller` exposes `fromDirectoryConfig`, `processResponse` & `extractRequest`. - - `Enrolled` exposes `extractRequest`, `processResponse` & `fallbackTarget`. - - `UncheckedProposal` exposes `extractTxToScheduleBroadcast`, `checkBroadcastSuitability` & `assumeInteractiveReceiver`. - - `MaybeInputsOwned` exposes `checkInputsNotOwned`. - - `MaybeMixedInputScripts` exposes `checkNoMixedInputScripts`. - - `MaybeInputsSeen` exposes `checkNoInputsSeenBefore`. - - `OutputsUnknown` exposes `identifyReceiverOutputs`. - - `ProvisionalProposal` exposes `substituteOutputAddress`, `contributeNonWitnessInput`, `contributeWitnessInput`, `tryPreservingPrivacy` & - `finalizeProposal`. - - `PayjoinProposal` exposes `deserializeRes`, `extractV1Req`, `extractV2Request`, `isOutputSubstitutionDisabled`, `ownedVouts`, `psbt` & - `utxosToBeLocked`. + +- ##### V1 + - `UncheckedProposal` exposes `fromRequest`, `extractTxToScheduleBroadcast`, `checkBroadcastSuitability`, `buildNonIncentivizing`, + `assumeInteractiveReceiver` &`alwaysDisableOutputSubstitution`. + - `MaybeInputsOwned` exposes `checkInputsNotOwned`. + - `MaybeMixedInputScripts` exposes `checkNoMixedInputScripts`. + - `MaybeInputsSeen` exposes `checkNoInputsSeenBefore`. + - `OutputsUnknown` exposes `identifyReceiverOutputs`. + - `ProvisionalProposal` exposes `substituteOutputAddress`, `contributeNonWitnessInput`, `contributeWitnessInput`, `tryPreservingPrivacy` & + `finalizeProposal`. + - `PayjoinProposal` exposes `isOutputSubstitutionDisabled`, `ownedVouts`, `psbt` & `utxosToBeLocked`. +- ##### V2 + - `Enroller` exposes `fromDirectoryConfig`, `processResponse` & `extractRequest`. + - `Enrolled` exposes `extractRequest`, `processResponse` & `fallbackTarget`. + - `UncheckedProposal` exposes `extractTxToScheduleBroadcast`, `checkBroadcastSuitability` & `assumeInteractiveReceiver`. + - `MaybeInputsOwned` exposes `checkInputsNotOwned`. + - `MaybeMixedInputScripts` exposes `checkNoMixedInputScripts`. + - `MaybeInputsSeen` exposes `checkNoInputsSeenBefore`. + - `OutputsUnknown` exposes `identifyReceiverOutputs`. + - `ProvisionalProposal` exposes `substituteOutputAddress`, `contributeNonWitnessInput`, `contributeWitnessInput`, `tryPreservingPrivacy` & + `finalizeProposal`. + - `PayjoinProposal` exposes `deserializeRes`, `extractV1Req`, `extractV2Request`, `isOutputSubstitutionDisabled`, `ownedVouts`, `psbt` & + `utxosToBeLocked`.