Release: develop -> main#3730
Merged
Merged
Conversation
) * fix(realunit): make register/wallet idempotent on signature match `completeRegistrationForWalletAddress` (and the same-wallet branch of `completeRegistration`) threw `BadRequestException("RealUnit registration already exists for this wallet")` whenever a KycStep already existed for the current wallet. That breaks legitimate client retries after a lost response: the first call succeeds server-side, the network drops the reply, the client re-sends with the same EIP-712 signature and gets a hard 400 — surfaced in the realunit-app KYC merge flow (RealUnitCH/app#466) as a user-stuck failure with no recovery path. Replace the hard throw with a signature-aware idempotency check: - Same wallet + same signature → return the existing registration's status (`COMPLETED` if the KycStep is completed, otherwise `FORWARDING_FAILED`). No new KycStep, no re-forward to Aktionariat. - Same wallet + different signature → keep the 400, but with the more precise message "RealUnit registration already exists for this wallet with a different signature". A fresh sign over the same wallet means the client produced a new payload — that is a real conflict, not a retry. Tests cover all three branches and assert that `createCustomKycStep` is never called on the idempotent paths. * refactor(realunit): destructure findRegistrationStep result and log idempotent retries - Use destructuring at both `findRegistrationStep` call sites so the register/complete and register/wallet paths read identically. - Pass `userData` explicitly into `idempotentRegistrationResult` rather than relying on TypeORM's back-population of `step.userData`, which is not guaranteed for steps loaded via the `userData.kycSteps` relation. - Emit an info log when the idempotent branch fires so production retry frequency is observable and stuck-user reports can be correlated to a kycStep id. - Document the three KycStep statuses REALUNIT_REGISTRATION actually reaches (INTERNAL_REVIEW / MANUAL_REVIEW / COMPLETED) so the binary `isCompleted` mapping does not silently break if the lifecycle is ever extended. * docs(realunit): broaden idempotent-status comment to cover admin overrides The previous comment claimed the step is in one of three states (INTERNAL_REVIEW / MANUAL_REVIEW / COMPLETED). That is true under the normal service flow, but the generic `kyc-admin.updateKycStep` endpoint can push REALUNIT_REGISTRATION into any non-failed/non-canceled status (ON_HOLD, OUTDATED, etc.) — and `findRegistrationStep` only filters FAILED and CANCELED. Runtime behavior is unchanged (anything that is not `isCompleted` maps to FORWARDING_FAILED, which is the safe default), but the comment now accurately reflects the reachable state set. * fix(realunit): match idempotency signatures case-insensitively EIP-712 signatures are 0x-prefixed hex strings. Lower-case and upper-case representations of the same signature are semantically identical, but the previous strict `!==` would have treated them as different and rejected legitimate retries that happen to flip hex case (can occur when a wallet library updates its hex-encoding default). Use `Util.equalsIgnoreCase` for the comparison, matching the convention already used for wallet-address comparisons in `findRegistrationStep`. Added a unit test that stores an upper-case signature and retries with a lower-case one — it now returns COMPLETED instead of throwing 400.
TaprootFreak
approved these changes
May 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automatic Release PR
This PR was automatically created after changes were pushed to develop.
Commits: 1 new commit(s)
Checklist