handleGenerate in app/auth/create.tsx sets saving via setState, but React state updates are asynchronous/batched — a sufficiently fast double-tap before the first re-render commits disabled={saving} to the native button could invoke handleGenerate twice, generating two keypairs where the second saveSecretKey call silently overwrites the first in SecureStore. If the UI already showed the first publicKey to the user (e.g. they screenshotted or wrote it down) before the race resolves, the user now has a recorded address they can no longer access.
Definition of done:
- Reproduce the race deterministically (e.g. via a synchronous double-invoke test) before fixing
- Fix with a ref-based synchronous guard, not another state variable that has the same batching problem
- Regression test asserting exactly one
saveSecretKey call regardless of tap speed
Before opening a PR for this issue, read CONTRIBUTING.md.
This is not a starter-issue. The Definition of done above is the full
acceptance criteria, not a subset to sample from — a PR that addresses part
of it is an unfinished issue, not a smaller one. Your PR must include, in
the PR description itself:
PRs missing these will be sent back before review, not reviewed and rejected — please do this up front.
handleGenerateinapp/auth/create.tsxsetssavingviasetState, but React state updates are asynchronous/batched — a sufficiently fast double-tap before the first re-render commitsdisabled={saving}to the native button could invokehandleGeneratetwice, generating two keypairs where the secondsaveSecretKeycall silently overwrites the first in SecureStore. If the UI already showed the firstpublicKeyto the user (e.g. they screenshotted or wrote it down) before the race resolves, the user now has a recorded address they can no longer access.Definition of done:
saveSecretKeycall regardless of tap speedBefore opening a PR for this issue, read CONTRIBUTING.md.
This is not a starter-issue. The Definition of done above is the full
acceptance criteria, not a subset to sample from — a PR that addresses part
of it is an unfinished issue, not a smaller one. Your PR must include, in
the PR description itself:
PRs missing these will be sent back before review, not reviewed and rejected — please do this up front.