Skip to content

Deprecate v2 SenderBuilder::new, fix FFI v1 panic - #1884

Merged
DanGould merged 1 commit into
payjoin:masterfrom
DanGould:deprecate-v2-sender-new
Sep 17, 2026
Merged

DanGould merged 1 commit into
payjoin:masterfrom
DanGould:deprecate-v2-sender-new

Conversation

@DanGould

Copy link
Copy Markdown
Member

Closes #1849. Replaces #1870.

payjoin::send::v2::SenderBuilder::new panics on a URI whose pj endpoint is BIP 78 only. That URI parses and passes check_pj_supported, so a QR code from any v1 receiver can crash a v2-only sender, and through payjoin-ffi that panic reached Bull Bitcoin Mobile as an opaque uniffi error.

Per the discussion on #1849, new keeps its signature and is deprecated in favor of from_parts, which takes the v2 PjParam directly and so makes the caller match on the URI's PjParam and decide what to do with a v1 endpoint. The rustdoc now states the panic and the migration path. In-repo tests move to from_parts, except the one that exercises new itself.

payjoin-ffi keeps its SenderBuilder::new constructor, since bindings have no matchable PjParam, but it now does the match internally and returns a new SenderInputError::UnsupportedPjVersion for v1 endpoints. The JavaScript integration test that relied on the panic (asserting RuntimeError) now checks the typed FeeRateOutOfRange error against a v2 URI and the new error against a v1 URI.

Testing: contrib/lint.sh, the cargo doc -D warnings gate, payjoin/contrib/test.sh (lib, integration, and the v1-only and v2-only compile checks), and the payjoin-ffi Rust unit tests all pass locally. The JavaScript binding test change was not run locally; it follows the getInner and instanceOf shapes the other tests in that file use, so I am relying on CI for it.

Disclosure: co-authored by Claude Code

@coveralls

coveralls commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 35198352125

Coverage decreased (-0.02%) to 86.687%

Details

  • Coverage decreased (-0.02%) from the base build.
  • Patch coverage: 1 uncovered change across 1 file (35 of 36 lines covered, 97.22%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
payjoin/src/core/send/v2/session.rs 36 35 97.22%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 16691
Covered Lines: 14469
Line Coverage: 86.69%
Coverage Strength: 339.02 hits per line

💛 - Coveralls

@DanGould

Copy link
Copy Markdown
Member Author

CI failures here led me to #1885. Really I'm seeking concept ACK @benalleng. FFI v1 send COULD be supported on top of this here, where we'd ignore receive but at least be able to send to widely deployed BTCPayServer. What do you think?

@benalleng benalleng left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

CACK 6e3adea

As long as we don't have access to PjParam this seems like the best way to approach this on the FFI side. Sadly there will be some doc discrepancy between the rust src and the FFI with the deprecated new() method, though I don't think our FFi overall was ever particularly well matched in the first place

I think we should leave the full v1 send as a followup. we can still release them in the same version if you want

@DanGould

DanGould commented Sep 16, 2026

Copy link
Copy Markdown
Member Author

I don't have plans to make further adjustments if this is ackable. Originally, I wanted to wait until #1885 went through because otherwise CI is broken.

I think this is ready to go as-is and should be much easier to swallow because it only makes aesthetic changes to the core payjoin crate.

@xstoicunicornx xstoicunicornx left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Overall this looks good to me.

One question I had is why don't we want to mark the FFI new method as deprecated as well?

We probably want to add the v1 guard to all the language bindings tests and not just javascript, though this could be taken as a follow up.

Waiting for rebase to confirm CI finishes cleanly before approving.

@DanGould

Copy link
Copy Markdown
Member Author

@xstoicunicornx my suggestion here is that at the FFI layer we make a breaking change because we haven't made a 1.0 commitment yet, RATHER than deprecate.

we do not yet have an alternative at the FFI layer. There is no from_parts function there.

@DanGould
DanGould force-pushed the deprecate-v2-sender-new branch from 6e3adea to 031cf66 Compare September 17, 2026 07:12
payjoin::send::v2::SenderBuilder::new panics on a URI whose pj endpoint
is BIP 78 only. Such a URI parses and passes check_pj_supported, so a
QR code from any v1 receiver could crash a v2-only sender. payjoin-ffi
forwarded URIs straight into that constructor, which is how Bull
Bitcoin Mobile hit an opaque uniffi panic when paying a v1 receiver.

Changing new to return a Result would be a semver-major change for the
1.0 crate. Instead, deprecate it and point callers at from_parts, which
takes the v2 PjParam directly and so forces the caller to match on the
URI's PjParam and decide what to do with a v1 endpoint. The docs now
state the panic and the migration path. In-repo tests move to
from_parts except for the one that exercises new itself.

The FFI SenderBuilder::new keeps its signature, since bindings have no
matchable PjParam, but now does the match internally and returns a new
SenderInputError::UnsupportedPjVersion for v1 endpoints instead of
panicking across the FFI boundary. The JavaScript integration test that
relied on that panic (asserting RuntimeError) now checks the typed
FeeRateOutOfRange error against a v2 URI and the new error against a
v1 URI.

Fixes payjoin#1849
@DanGould
DanGould force-pushed the deprecate-v2-sender-new branch from 031cf66 to 44bc40d Compare September 17, 2026 08:11
@DanGould

Copy link
Copy Markdown
Member Author

Regarding the tests, I think we can wait for #1866 and include it on top of that rather than write 5x test fixtures to clean up. I'll make a comment there to follow on with it.

@xstoicunicornx xstoicunicornx left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

utACK 44bc40d

Straightforward updates to deprecate the SenderBuilder::new method. Agree with the decision to deprecate rather than introduce breaking change to the method's signature. Also agree with the recommendation to use SenderBuilder::from_parts rather than creating a new fallible version of SenderBuilder::new, as the new version wouldn't provide much additional utility regardless of whether implementor is using only v2 or both v1 and v2.

@DanGould
DanGould merged commit a42e6f3 into payjoin:master Sep 17, 2026
57 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FFI sender doesn' support v1 payjoin URIs

4 participants