Skip to content

fix(expo): prevent duplicate purchase requests - #451

Merged
hyochan merged 1 commit into
mainfrom
codex/guard-expo-purchase-reentry
Sep 13, 2026
Merged

hyochan merged 1 commit into
mainfrom
codex/guard-expo-purchase-reentry

Conversation

@hyochan

@hyochan hyochan commented Sep 13, 2026

Copy link
Copy Markdown
Member

Repeated presses could start two native purchases before React disabled the Expo example's Purchase button. Keep one request pending at a time and allow another after it settles. A regression test invokes the same render's handler twice and checks that cancellation allows retry.

Checks: Expo lint and TypeScript passed; 454 library, 82 plugin, and 141 example tests passed. Pre-commit parity, layout, sponsor, and IAPKit contract audits passed.

Device evidence: iPhone 13 mini and Pixel 2 completed real Apple Sandbox and Google Play test purchases through the local IAPKit server and DEV Convex. Each created one purchase row; replay kept the same row and total. After the fix, Pixel 2 keyboard input produced one native request, zero overlapping-request errors, and successful cancellation with the button enabled again. The iPhone purchase preceded this JavaScript guard; no native code changed.

The change only affects the example's request guard. These results do not establish a live subscription-webhook integration with the separate Commerce example or an external product. Existing Commerce fixture evidence remains scoped as documented.

Summary by CodeRabbit

  • Bug Fixes
    • Prevented multiple purchase requests from being initiated by rapid, repeated presses.
    • Purchase requests can be started again after the previous request completes or is canceled.
    • Preserved existing cancellation and error reporting behavior.

@hyochan hyochan added 🐛 bug Something isn't working 👀 example expo-iap expo-iap library labels Sep 13, 2026
@coderabbitai

coderabbitai Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 695e697f-450f-4079-a09d-0d8d3da66e33

📥 Commits

Reviewing files that changed from the base of the PR and between baabc40 and 0ed6fbb.

📒 Files selected for processing (2)
  • libraries/expo-iap/example/__tests__/purchase-flow.test.tsx
  • libraries/expo-iap/example/app/purchase-flow.tsx

Included review availability: Your plan provides up to 2 included reviews per hour; 1 remains after this review.


📝 Walkthrough

Walkthrough

The purchase flow now blocks concurrent purchase requests with a pending-state guard. The guard clears after resolution or rejection. A test covers rapid presses, cancellation, and a subsequent purchase.

Changes

Purchase request concurrency

Layer / File(s) Summary
Pending request guard
libraries/expo-iap/example/app/purchase-flow.tsx
handlePurchase ignores attempts while a request is pending. The guard resets after success or failure. Existing cancellation and formatted failure handling remain.
Concurrency regression test
libraries/expo-iap/example/__tests__/purchase-flow.test.tsx
The test confirms that two rapid presses start one request, and that a later press starts another after cancellation.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 0ed6f

The purchase guard blocks overlapping requests and is released after cancellation or other failures, so the change is ready to merge.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: preventing duplicate purchase requests in the Expo example.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/guard-expo-purchase-reentry

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Sep 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 76.16%. Comparing base (baabc40) to head (0ed6fbb).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #451   +/-   ##
=======================================
  Coverage   76.16%   76.16%           
=======================================
  Files         157      157           
  Lines       16676    16676           
  Branches     4807     4807           
=======================================
  Hits        12702    12702           
  Misses       3974     3974           
Flag Coverage Δ
expo-iap 90.30% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
React Native IAP 93.11% <ø> (ø)
Expo IAP 90.30% <ø> (ø)
flutter_inapp_purchase 90.42% <ø> (ø)
IAPKit Server 92.05% <ø> (ø)
IAPKit Convex 61.52% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@hyochan
hyochan merged commit 32c8e58 into main Sep 13, 2026
45 checks passed
@hyochan
hyochan deleted the codex/guard-expo-purchase-reentry branch September 13, 2026 08:37
@hyochan

hyochan commented Sep 13, 2026

Copy link
Copy Markdown
Member Author

Available on main in 32c8e58. All PR checks passed. This example-only fix does not require a package release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐛 bug Something isn't working 👀 example expo-iap expo-iap library

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant