Repository navigation
0.3.0
Two of the three WooCommerce retrofit findings. Both fix bugs that mis-settled or crashed real orders; neither touches the database schema. The third (sync cursor per account and network, testnet-reset recovery) needs a migration in every adapter and ships separately as 0.4.0 — see #3.
Breaking for adapters
| Change | What to do |
|---|---|
findTransaction() → findTransactions() |
Return all rows for the destination/tag pair, ORDER BY ledger_index DESC, id DESC |
nextDestinationTagSequence() contract |
Seed the counter row with random_int(0, 2**31 - 1), never 0; the counter table must survive uninstall |
SyncService::findTransaction() is likewise replaced by findTransactions() plus findTransactionFor(PaymentIntent).
Choosing the paying transaction by asset class
A destination tag can carry more than one transaction. The old code took whichever row the primary key surfaced first, which in the dev shop meant a foreign 0.84 XRP payment settled order #133, and an old RLUSD payment handed to an XRP intent made withFulfillment() reject the shape — aborting the sync and leaving order #135 open forever with the real payment sitting there unexamined.
SyncService::findTransactionFor() now picks the newest candidate whose delivered amount matches the quote's asset class. A candidate in the right class but from the wrong issuer is deliberately kept rather than skipped: it is a real payment attempt, and SettlementPolicy is what declares it non-settling, so a shop can tell the customer their token was wrong instead of showing them nothing. Non-payments and unreadable "unavailable" amounts are skipped and logged, never a reason to abort a sync.
Random destination-tag starts
The permutation's multiplier and offset are public constants, so a counter starting at 0 produced the same tag sequence in every installation — sequence 0 is always 114729. Two shops on one receiving account issued identical tags and settled each other's orders. The counter now starts at random_int(0, 2**31 - 1), which leaves ~2.1 billion sequences, so the range still needs no wraparound and DestinationTagsExhaustedException stays reachable. DestinationTagService itself is unchanged — the permutation is a bijection over the whole range and does not care where the counter starts.
Also now contractual: ledger_direct_xrpl_destination_tag must survive uninstall. It is the only record that a tag was already issued.
Notes
WooCommerce 1.0.0 carries local workarounds for both findings (findTransactionsByTag(), findPaymentFor()); drop them in favour of the core versions when raising the constraint. 117 tests, green on PHP 8.2 / 8.3 / 8.4 plus the lowest-dependency job. Contract details in INVARIANTS.md under Settlement and Tables.