Skip to content

Release: develop -> main - #207

Open
github-actions[bot] wants to merge 15 commits into
mainfrom
develop
Open

Release: develop -> main#207
github-actions[bot] wants to merge 15 commits into
mainfrom
develop

Conversation

@github-actions

@github-actions github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

Automatic Release PR

This PR was automatically created after changes were pushed to develop.

Commits: 3 new commit(s)

Checklist

  • Review all changes
  • Verify CI passes
  • Approve and merge when ready for production

DFX and others added 15 commits July 29, 2026 16:29
 - @dfx.swiss/react@1.7.0-beta.1
…unt (#204)

* feat(core,react): let the buy invoice call target the collection account

PUT buy/paymentInfos/:id/invoice accepts an optional collectionAccount
query switch: when set, the API issues the invoice against the shared DFX
collection account instead of the personal virtual IBAN stored on the
request (DFXswiss/backend#4686).

The switch lives in BuyUrl.invoice, the single place that owns the URL
shape, and is passed through by both callers — BuyApi.getInvoice and
useBuy().invoiceFor. Putting it in either caller would have placed the
query form next to the other one instead of inside it.

The parameter is omitted rather than sent as false, because the API maps
any present value to true (Util.mapBooleanQuery). It is optional, so
every existing caller stays source-compatible: this is additive.

Consumer: DFXswiss/app#1270, which currently hand-builds this URL
through useApi() because the SDK does not carry the switch.

* refactor(core,react): build the collection-account query the way the repo does

Review found the first commit hand-rolled the query inside the URL builder.
That is the construct commit c6c0411 ("Improve @dfx.swiss/core package
quality", #152) removed across the package: definitions/*Url carries the
path, the core client builds its query with Utils.buildQuery, and the react
hook builds it inline. The exact twin is the optional includeTx switch —
SwapApi.ts:14 and SellApi.ts:14 on the client side, swap.hook.ts:23 and
sell.hook.ts:20 in the hooks.

So BuyUrl.invoice is back to its develop state, BuyApi.getInvoice follows
SwapApi.createPaymentInfo, and useBuy().invoiceFor follows swap.hook.ts. The
resulting URLs are unchanged.

Also drops the comment attributing the design to Util.mapBooleanQuery. That
attribution was wrong: this endpoint compares the query against the literal
'true' (DFXswiss/backend#4686) and deliberately does not use presence semantics.
Omitting the parameter on false stays correct; only the stated reason was.

The three getInvoice tests now assert the returned document as well. Without
that, an implementation returning a wrong object passed all of them and
tsc -b too, while both sibling specs in the same directory already assert it.

* refactor(react): narrow the change to exactly the requested hook edit

The review on DFXswiss/app#1270 asked for one thing: give
useBuy().invoiceFor an optional collectionAccount parameter so the app stops
hand-building the request. It supplied the code and called it a two-line
change in buy.hook.ts.

The previous two commits went further — they widened BuyApi.getInvoice and
added a core test file. Both are reverted here. BuyApi.getInvoice has no
caller in this monorepo or in services and was reachable only through
DfxApiClient.buy, so widening it was not required to unblock the consumer,
and carrying it made this PR larger than what was asked for.

What remains is the reviewer's own code, verbatim: the optional parameter on
the interface, and the ternary inline in the call. Every existing caller stays
source-compatible.

Consequence, stated rather than hidden: the switch ships with no test.
@dfx.swiss/react defines no test script — per CONTRIBUTING only core and
bip322-multisig do — and this PR does not add test infrastructure to react.
The same is true today for the includeTx switch in swap.hook.ts and
sell.hook.ts.

* test(core): cover the collection-account switch on the buy client

The hook edit alone shipped the switch untested: @dfx.swiss/react has no test
runner, so nothing in this repo would have noticed if the parameter stopped
being forwarded.

BuyApi.getInvoice calls the same endpoint and lives in the one package that
does run tests, so the switch is covered there. It follows the pattern the
package already uses for optional boolean queries — Utils.buildQuery with
`value || undefined`, exactly as SwapApi.createPaymentInfo and
SellApi.createPaymentInfo handle includeTx. BuyUrl.invoice stays path-only.

The hook keeps the form the review asked for; core and hook build the query
differently, which is the same split swap.hook.ts/SwapApi.ts and
sell.hook.ts/SellApi.ts already have. Both produce identical URLs for every
value the type permits.

Three tests, each asserting the full request options and the returned
document. Verified by mutation: dropping `|| undefined` fails 2 of 3, not
appending the query fails 1 of 3, returning a wrong document fails 3 of 3.
 - @dfx.swiss/core@0.7.0-beta.0
 - @dfx.swiss/react@1.8.0-beta.0
…e be sent again (#210)

* fix(react): keep the support chat sync alive and settle messages by id

The 5-second sync was a chain, not a loop: each run scheduled the next only
because it changed state, so a single failed request ended it for good and the
chat silently stopped receiving messages.

- run the sync on a real interval, reading current state through refs
- settle optimistic messages by id instead of index, so parallel uploads and a
  message at position 0 land correctly
- anchor the delta on the highest settled id, falling back to a full sync
- drop the optimistic entry when a sync already delivered the settled message
- replace state instead of mutating it, so StrictMode no longer duplicates
- add a jest setup for the package, which lerna previously skipped

* feat(react): let a failed message be sent again

A send that fails keeps its negative placeholder id and lives only in this
context, so the text was unreachable: nothing could retry it and nothing could
remove it. The next loadSupportIssue rebuilt the state from the server and the
customer's message was gone.

retryMessage claims the entry in place, puts it back to Sent and runs the same
path as the first attempt. Unknown or already-sent ids are a no-op, so a double
click cannot send twice.

* fix(react): drop a sync response that belongs to a different ticket

The five-second sync reads the open issue from a ref, asks the API for it, and
merges whatever comes back into whatever is open by then. Nothing compared the
two. Switching tickets while a getIssue is in flight therefore merged the old
ticket's messages into the new one -- foreign conversation inside an open
support chat. The ref lags the state by an effect tick, which widens the window,
and keeping the sync alive after an error widens it further.

Compare the uid and discard a response that does not belong to the issue on
screen. The comparison lives with the other pure message helpers so it is
covered by their tests.
 - @dfx.swiss/react@1.8.0-beta.1
* Add the Yapeal member to the PersonalIbanProvider enum

The API accepts 'Yapeal' as an explicit personalIbanProvider selector on the
buy payment-info request: it returns the customer's existing active legacy
Yapeal personal IBAN, fail-closed, and never issues a new one. The frontend
needs the member to build the provider switch next to the payment details.

The enum string values are wire format, so a test pins them.

* test(core): prove the personalIbanProvider wire transport

The enum-value pin compared the member to its own literal - a tautology
that stays green if BuyApi stops forwarding the field. The new case calls
createPaymentInfo against the mocked HTTP client and asserts the raw
'Yapeal' string on the forwarded request data.

* feat(core,react): serve the personal-IBAN row list through the SDK

The buy flow needs the customer's personal-IBAN rows (now carrying the
issuing bank) to decide whether a legacy Yapeal row exists before choosing
the default provider. GET buy/personalIban joins the SDK as
BuyApi.getPersonalIbans and useBuy().getPersonalIbans with the VirtualIban
type, so the frontend consumes the endpoint through the SDK instead of a
hand-built call. A transport test pins the request shape.

* style(react): annotate getPersonalIbans with its promise return type

Every other callback in the package spells the return type; the new
getter was the single exception.
 - @dfx.swiss/core@0.7.0-beta.1
 - @dfx.swiss/react@1.8.0-beta.2
…#224)

* Scope develop PR CI to changed packages and honour ci:full

Lerna lint, format, build and test run with --since on develop PRs.
The ci:full label, main, workflow_dispatch, infrastructure changes
and deletions under packages/ force the full workspace run.

* Fail-closed on unknown scope mode and name every full-run trigger

Root eslint/prettier configs force a full Lerna run. Task steps
reject an unknown mode. CONTRIBUTING lists the exact triggers.

* Match CONTRIBUTING and the infra comment to the full-run list

Spell out the safe path set and name eslint/prettier in the
infrastructure comment. Local Lerna commands always cover every package.
…lop (#225)

* Reject pull requests into main that are not from develop

GitHub cannot restrict the source branch natively. This required check
allows only this repository's develop branch to target main.

* chore(ci): fail closed when pull_request head metadata is empty

Empty strings pass set -u. Without this check a missing repo name
plus head ref develop would accept the pull request.
Add a unit spec for every public method and for the private filter
query builder via exportCsv and getHistory.
 - @dfx.swiss/core@0.7.0-beta.2
 - @dfx.swiss/react@1.8.0-beta.3
Historical closes-links must keep resolving after the new api repo exists.

Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
 - @dfx.swiss/core@0.7.0-beta.3
 - @dfx.swiss/react@1.8.0-beta.4
Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
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.

3 participants