Skip to content

feat(x402-e2e): concurrent commit-and-redeem scenario (20 parallel buyers)#82

Merged
levalleux-ludo merged 2 commits into
add-x402-e2e-post-commit-lifecyclefrom
add-x402-e2e-concurrent-commit-redeem
May 21, 2026
Merged

feat(x402-e2e): concurrent commit-and-redeem scenario (20 parallel buyers)#82
levalleux-ludo merged 2 commits into
add-x402-e2e-post-commit-lifecyclefrom
add-x402-e2e-concurrent-commit-redeem

Conversation

@levalleux-ludo
Copy link
Copy Markdown
Member

Summary

  • New @p0 scenario file concurrent.test.ts — 20 fresh EOAs fire fetch(/resource) concurrently against an in-process resource server, each going through atomic commit-and-redeem (the A2 wire path). Surfaces concurrency regressions the existing single-buyer scenarios can't catch (relayer nonceManager, offer-template signing under contention, subgraph indexer under load).
  • E2E_DOCKER_KEEP_STACK=1 escape hatch on globalSetup — preserves a stack the maintainer brought up via pnpm stack:up so individual scenario files can be re-run repeatedly without paying the full cold-start cost.

Upstream tweaks bundled with the test

Three concurrency limits had to be addressed for the test to land green. Each is documented inline:

  • example-resource-server offer saltingbuildUnsignedOffer now folds the per-request sessionId into metadataUri / metadataHash. Without it, two concurrent requests within the same millisecond produce byte-identical UnsignedFullOffer structs and the second commit reverts OfferSoldOut() on the single-quantity template.
  • example-resource-server widened validity windows — offer + voucher windows go from 1 h to 30 d (with 1 d backdate). Hardhat's block.timestamp advances 1 s per block; at 50 ms interval mining chain time runs ~20× wall-clock, so the prior 1 h window expired in ~3 min of suite wall-clock.
  • x402-e2e/globalSetup interval mining — switches Hardhat from automine to 50 ms interval mining right after [stack] ready. Default automine rejects concurrent meta-tx submissions from a single relayer with "transactions can't be queued when automining"; interval mining lets them queue and mine in batches.

Run modes

# Mode 1 — full suite (existing convention, the test runs alongside everything else):
E2E_DOCKER=1 pnpm --filter @bosonprotocol/x402-e2e test

# Mode 2 — repeatable against a stack you launched manually:
pnpm --filter @bosonprotocol/x402-e2e stack:up
E2E_DOCKER=1 E2E_DOCKER_KEEP_STACK=1 \
  pnpm --filter @bosonprotocol/x402-e2e exec vitest run test/scenarios/concurrent.test.ts
# (re-run as many times as you want — fresh EOAs each run)
pnpm --filter @bosonprotocol/x402-e2e stack:down

Test plan

  • pnpm -r build — every workspace package builds clean
  • pnpm -r lint — zero warnings
  • pnpm format:check — clean
  • pnpm --filter @bosonprotocol/x402-example-resource-server test — 11/11 unit tests pass (cache + offer building still green after the sessionId plumbing)
  • Mode 1 (full e2e suite, fresh stack): 7 test files passed, 36 tests passed, 1 skipped, 30 todo — A1, A2, new E0 (concurrent), B1B7, harness, stack — all green; stack tears down cleanly at the end
  • Mode 2 (E2E_DOCKER_KEEP_STACK=1, preserved stack): ran the concurrent test twice in a row against the same stack — both green, stack preserved between runs

This PR is stacked on #76 (add-x402-e2e-post-commit-lifecycle); base auto-rebases to main when that merges.

🤖 Generated with Claude Code

…l buyers)

E0 — 20 fresh EOAs fire `fetch(/resource)` concurrently against an
in-process resource server, each going through atomic
commit-and-redeem. Surfaces concurrency regressions the existing
single-buyer scenarios can't catch (relayer nonceManager, offer
template signing, subgraph indexer under load).

Three upstream tweaks were needed to land the test green:

- example-resource-server: fold the per-request session id into
  `metadataUri` / `metadataHash` so concurrent buyers each get a
  distinct `predictedOfferId`. Without it, two requests within the
  same millisecond produce byte-identical `UnsignedFullOffer`
  structs and the second commit reverts `OfferSoldOut` on the
  single-quantity template.
- example-resource-server: widen offer + voucher validity windows
  from 1 h to 30 d (with 1 d backdate) so they tolerate Hardhat's
  ~20x chain-time acceleration under interval mining.
- x402-e2e/globalSetup: switch Hardhat to 50 ms interval mining
  right after `[stack] ready`. The default automine rejects
  concurrent meta-tx submissions from a single relayer with
  "transactions can't be queued when automining"; interval mining
  lets them queue and mine in batches.

Also adds an `E2E_DOCKER_KEEP_STACK=1` escape hatch on globalSetup
so individual scenario files can be re-run repeatedly against a
stack the maintainer brought up via `pnpm stack:up` — useful for
iterating without paying the full cold-start cost each run.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 85e67354-64c0-4f20-bf47-0106d3544f1a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-x402-e2e-concurrent-commit-redeem

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

@levalleux-ludo levalleux-ludo marked this pull request as ready for review May 21, 2026 10:28
Copilot AI review requested due to automatic review settings May 21, 2026 10:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an x402-e2e concurrency scenario and supporting harness/example-server adjustments to make concurrent commit-and-redeem flows reliable against the local Docker stack, plus a dev “keep stack running” mode to speed up iteration.

Changes:

  • Add concurrent.test.ts scenario that runs 20 parallel buyers through the atomic commit-and-redeem (A2) path.
  • Update e2e globalSetup to enable 50ms interval mining and to support E2E_DOCKER_KEEP_STACK=1 (skip pre-stop and post-teardown).
  • Update example resource server offer-building to salt offers with a per-request session id and widen validity windows to tolerate Hardhat time drift under interval mining.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
typescript/packages/x402-e2e/test/setup/globalSetup.ts Adds KEEP_STACK mode and switches Hardhat from automine to interval mining to allow queued concurrent txs.
typescript/packages/x402-e2e/test/scenarios/concurrent.test.ts New E0 scenario: 20 parallel buyers execute commit-and-redeem concurrently and assert on unique exchanges + REDEEMED state.
typescript/packages/x402-e2e/test/scenarios/_seed-wallets.ts Adds a dedicated seed-wallet slot for the new concurrent scenario.
examples/resource-server/src/offer.ts Salts metadata with sessionId to avoid identical offers under concurrency; widens offer/voucher windows.
examples/resource-server/src/app.ts Plumbs sessionId into buildUnsignedOffer.
CLAUDE.md Documents E2E_DOCKER_KEEP_STACK=1 workflow for iterative scenario runs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread typescript/packages/x402-e2e/test/setup/globalSetup.ts
@levalleux-ludo levalleux-ludo merged commit c2ef3c4 into add-x402-e2e-post-commit-lifecycle May 21, 2026
1 check passed
@levalleux-ludo levalleux-ludo deleted the add-x402-e2e-concurrent-commit-redeem branch May 26, 2026 09:03
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.

2 participants