Skip to content

v6.13.0 - #2678

Merged
ethicnology merged 431 commits into
mainfrom
develop
Aug 14, 2026
Merged

v6.13.0#2678
ethicnology merged 431 commits into
mainfrom
develop

Conversation

@ethicnology

Copy link
Copy Markdown
Member

No description provided.

i5hi and others added 30 commits July 27, 2026 15:15
The disclaimer dialog resolved a datasource from the service locator inside
a widget, so the ui layer talked straight to data (AGENTS.md rules #2/#6),
and the receive feature reached into settings/ui/widgets for it (rule #1).

The flag now travels the normal chain: a PayjoinDisclaimerRepository
interface in domain, a SharedPreferences implementation in data, two
usecases, and SettingsCubit holding the state. One boolean does not justify
a datasource forwarding two calls to a repository forwarding them back, so
it collapses into the repository. The dialog becomes passive and moves to
core/widgets, which also drops the cross-feature import: both call sites
show it, then record it — never the other way round.
The seven keys this branch adds (disclaimer title and settings row, advanced
settings title, the receive Additional Information tile and its placeholder,
the message-for-sender label, the send-confirm payjoin row) were en-only.

Short labels, not disclosure prose: PAYJOIN_FEATURES_PLAN F9 keeps the two
disclaimer explanations on the translator pipeline, and those are untouched
here. "Payjoin" stays untranslated in every locale, as the reviewed corpus
already does (transactionStatusPayjoinAborted). Machine-authored — worth a
native pass whenever the locale is next reviewed.
Pin payjoin crate to 1.0.0-rc.5 via SatoshiPortal fork
refactor(payjoin): UX updates from clean-install testing
Recovery was tied to locator setup, so foreground and background composition paths could instantiate protocol execution, while obsolete Workmanager schedules remained registered.

Resolve the repository lazily, start recovery explicitly from foreground app initialization, cancel persisted background schedules, and keep log pruning on foreground cold start.
Session, expiry, watcher, disable, and restart callbacks could race through whole-row SQLite updates. A stale callback could overwrite terminal state, while a local failure after network publication could trigger a competing fallback or strand polling.

Serialize effects per session and UTXO selection globally, use conditional monotonic SQLite transitions, reconcile both Payjoin and original transactions, resume unfinished sessions, retain retrying watchers until persistence converges, and reject duplicate sender publication. Cover the races with repository and independent-connection SQLite tests.
Disabling Payjoin settled active receivers before storing the setting. A transient settlement failure therefore left Payjoin enabled and able to accept new requests despite the user's choice.

Persist the disabled setting first, then settle every receiver best-effort. Unresolved sessions remain durable for foreground startup recovery, while the setting stays fail-closed and prevents new receiver creation.
The receive summary derived its sats or fiat suffix through a non-reactive bloc read, so changing the selected unit or exchange-rate-backed value could leave stale text on screen.

Select the complete derived suffix from ReceiveBloc state so the summary rebuilds whenever any of its amount, unit, currency, or exchange-rate inputs change.
Integration cleanup could expire rows while their PDK polling timers were still active, and three unimplemented scenarios used empty test bodies that reported false success.

Stop each recovered poll before marking its row expired, and mark restart and insufficient-funds scenarios as explicitly skipped with the fixture or harness each still requires.
fetchReceivers and fetchSenders still carried an onlyOngoing branch with no caller: the disable sweep and startup recovery deliberately read every row and decide from the freshest one under a session lock. A test stub also still referenced the dead parameter.

Remove the parameter and its filtering branch, leaving filtered reads to fetchAll, and drop the stale stub.
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
ethicnology and others added 14 commits August 13, 2026 11:34
Build 212 uploaded and processed as VALID, but the workflow failed afterwards because its Developer API key cannot PATCH usesNonExemptEncryption. Apple documents ITSAppUsesNonExemptEncryption in Info.plist as the way to supply the same declaration with the app.

Record false, matching the value read back from the last manually submitted valid build (204), and remove the action input so future uploads do not attempt a metadata PATCH that this deliberately least-privileged key cannot perform.
Build 212 proved the relevant release path end to end: both rustup binaries were wrapped, no rust-std target was downloaded during the Xcode archive, the signed IPA carried build number 212, artifact preservation succeeded, and Apple processed the upload as VALID.

Remove the DEBUG/verbose diagnostics and their temporary make argument. Also remove the mutex: the root cause was cargokit reaching the second, unwrapped rustup and floating to stable 1.97.1. With both binaries pinned, all toolchains and targets are installed serially before Xcode and the successful run performed no Rust target install during the archive. Keeping a global rustup lock would unnecessarily serialize cargo builds and its timeout path could violate lock ownership.

Keep the two-wrapper pin and its fail-fast assertions, and replace silent version/bundle tests with actionable annotations.
The App Store already contains builds 200 through 204, and the first successful CI upload created valid build 212 even though the subsequent metadata PATCH made the GitHub job red. Neither 200 nor 205 can now be reused for version 6.13.0.

Set the shared pubspec build number to 213 and make it the only source of truth. Android already maps it to versionCode; iOS now maps it to CFBundleVersion after the Xcode override fix. Remove the workflow-run offset and the manual iOS-only override so the two stores cannot silently diverge again.
fix: resolve 61 security audit findings, mitigate 7, document 5 upstream
fix(ios): stabilize App Store Connect release uploads
# Conflicts:
#	ios/Runner/AppDelegate.swift
#	lib/features/send/domain/usecases/create_send_swap_usecase.dart
#	lib/features/send/presentation/bloc/send_cubit.dart
#	lib/features/transactions/application/usecases/get_transactions_usecase.dart
#	lib/features/transactions/transactions_locator.dart
#	localization/app_en.arb
#	localization/app_es.arb
#	localization/app_fr.arb
#	test/features/transactions/application/usecases/get_transactions_usecase_test.dart
docs(release): document 6.13.0 changes
@ethicnology ethicnology self-assigned this Aug 13, 2026
@ethicnology

Copy link
Copy Markdown
Member Author

@claude do you have any suggestion about that release

keep in mind:

  • not applicable to the release. Boltz has been shut down and there are no funded legacy Boltz swaps awaiting settlement. Re-enabling orphaned restore/rescue routes would not restore an unavailable service. Dead Boltz UI/code can be removed separately.
  • no supported public release ships schema 14. origin/main and v6.12.2/v6.12.5/v6.12.6 all ship schema 13, so production upgrades execute the final 13→14 migration. Internal development builds are not a supported migration cohort and must reinstall.
  • not reproducible at HEAD. Lightning receive creates and persists a dedicated destination address inside CreateReceiveOrderSwapUsecase; the normal Liquid address-refresh handler does not retarget an active Lightning order.
  • obsolete for the Exchange flow. Cross-chain send-max is explicitly rejected, while regular max uses spendable balance and drain semantics.
  • therefore do not gate this release under the stated operational and support constraints.

#2563 (comment)

@claude

This comment was marked as resolved.

@ethicnology

Copy link
Copy Markdown
Member Author

We removed PAYJOIN_PACKAGE_PLAN.md now that the package migration is complete. We confirmed that rollback remains hotfix-forward only, but we will keep that as an internal operational constraint rather than add it to the public changelog, since users cannot downgrade through the stores.

@ethicnology

Copy link
Copy Markdown
Member Author

Test failing because Bob's mnemonic on testnet is empty

@ethicnology
ethicnology merged commit e94df75 into main Aug 14, 2026
6 of 8 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.

7 participants