feat(payjoin): exchange buy/sell/pay integration + issue fixes - #2538
Conversation
|
@claude review |
|
Claude finished @ethicnology's task in 6m 30s —— View job Code review — PR #2538 (payjoin exchange buy/sell/pay integration + issue fixes)
OverviewThis PR wires payjoin into all three exchange flows (buy = receiver session whose BIP21 URI is handed to the exchange at order creation; sell/pay = sender session against the order's High — the pay flow is missing the #2522 protections the sell flow receivedThe sell bloc got a careful broadcast latch (
Medium
Low / nits
What's done well
Verification notes
|
97f097c to
f31c632
Compare
84dac62 to
f0e92e7
Compare
The API legitimately sends order values the app refused to parse: status 'Expired' (distinct from 'Payment deadline expired'), payout status 'Failed', order type 'Sell USDT', empty payin/payout statuses, and null exchange rate and confirmation deadline fields on admin-initiated orders. Both batch parse layers turned the first such order into an empty list, hiding every exchange transaction in the app. - Parse per element with skip-and-log at both layers (datasource listOrderSummaries and repository getOrders), and in getOrderByTxId. - Make OrderStatus, OrderPayinStatus, OrderPayoutStatus and OrderType tolerant of unknown values; add the known missing members. - Render unknown order types generically via a new Order.generic variant carrying the server-sent type name. - Relax exchangeRateAmount, exchangeRateCurrency and confirmationDeadline to nullable, matching the server contract, with null guards at their consumers. - Read reward amounts from the payout side; the payin side is empty for admin-initiated orders and rendered every reward as 0 sats. - Derive fiat-vs-sats display from the order instead of a hardcoded variant list, fixing fiat refunds shown as sats and BTC balance adjustments formatted as fiat. Closes #2526 Closes #2527
…method
- Show the network on default wallets in the buy dropdown: Instant
payments (L-BTC on Liquid) / Secure Bitcoin (BTC on Bitcoin chain).
External and custom wallets keep their own names.
- Split the confirm page's Payout method row into Payout wallet and
Payout method, sharing the network phrases with the dropdown.
- Success message now includes what was paid: 'You bought {amount}
with {fiatAmount}' from the order's payin side.
- Below-minimum (and any other) order-creation failures are no longer
silent: the amount screen renders limit errors with the server's
amount and currency, and everything else through a neutral fallback
message. Previously only below-min/above-max variants rendered, and
most server errors never mapped to them, leaving Continue dead.
- Make the createOrder error parsing total via a shared Never-typed
helper across buy, sell, pay and withdraw: an error response can no
longer fall through to the result cast. Parses the server's singular
reason and new plural reasons shapes (API-Orders#859), tolerating
empty and limit-less entries.
- Stop converting fiat limit amounts with btcToSats: a 20 CAD minimum
rendered as 2,000,000,000 sats. Error entities now carry amount and
currency verbatim; the render site formats fiat as fiat.
- Repair broken translations the changed keys touched (zh/fa/th/tr
buyYouBought, zh payout-method and external-wallet strings).
Closes #2515
Closes #2516
Closes #2517
Closes #2518
…update
- 'Payment in Progress!' now says what is happening: 'The payment of
{fiatAmount} to {recipient} will be sent after your transaction
receives 1 confirmation onchain', with the recipient resolved from
the order (name, then label, then account identifier). Same
treatment on the completed screen, and the details table gains a
Recipient row.
- Once the payin confirms, the copy switches to 'Your transaction is
confirmed. The payment ... is being processed', driven by the
existing 5s poll.
- The success state now carries the post-broadcast order instead of
the stale pre-broadcast snapshot the bloc fetched and discarded.
- Transaction details: pull-to-refresh, and a proper error state with
Retry instead of skeletons that spin forever when the load fails.
- New localization keys instead of editing the old ones, so stale
translations fall back to English rather than silently dropping the
amount and recipient.
Closes #2524
Closes #2525
The Network fee priority row on the sell and pay confirmation screens was a debugPrint stub and every transaction paid the fastest rate. - SellBloc and PayBloc implement the shared fee modal's view-state and actions ports, following SendCubit's semantics: preset selection, custom sat/vB or absolute fees with arm/disarm/finalize, epoch-guarded previews, and a relay-floor gate on finalize. - The row opens the shared FeeOptionsModal and shows the committed selection; the summary fee reprices from a real PSBT built at the selected rate on every change. - Confirm prepares, signs and broadcasts at the committed selection. Unlike send and swap, the preview PSBT is display-only: sell and pay rebuild at broadcast time because a price-lock refresh can move the order's payin amount. The built fee is re-asserted against the relay floor before signing. - Fee editing locks while a confirmation is in flight or the payin is broadcast; handlers re-read live state so queued events are dropped, and every post-await emit merges into live state - a recalculation or preview landing after the flow moved on emits nothing instead of resurrecting a pre-broadcast state. - Previews price against the order's real payin address. Closes #2521
f31c632 to
40a9f6b
Compare
Bundles the Payjoin Exchange integration (buy/sell/pay toggle, session negotiation, txid resolution, labels) with fixes for issues touching the same buy/sell/pay/transactions surfaces.
Closes #2515, #2516, #2517, #2518, #2521, #2522, #2523, #2524, #2525, #2526, #2527, #2530