Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
daf7257
examples(scenarios): HTTP-wire capture cross-package integration test
vraspar May 19, 2026
3bdc403
examples(scenarios): source AUTH_CAPTURE_ESCROW from chainConfig inst…
vraspar May 19, 2026
c3b5378
examples(scenarios): share testAccounts + balance-slot helpers with h…
vraspar May 20, 2026
77b9c04
examples(scenarios): await 'listening' before returning URL from in-p…
vraspar May 20, 2026
aaaf179
examples(scenarios): use viem's numberToHex instead of pad + hex stri…
vraspar May 20, 2026
76ad609
examples(scenarios): close http.Server before rejecting on bind error…
vraspar May 20, 2026
22ea6df
examples(scenarios): derive deadlines from block.timestamp instead of…
vraspar May 20, 2026
367723b
examples(scenarios): assert escrow.paymentState(hash) matches after a…
vraspar May 20, 2026
5d67394
Merge branch 'main' into vraspar/http-wire-scenario
vraspar May 20, 2026
4d5a742
Merge branch 'main' into vraspar/http-wire-scenario
vraspar May 20, 2026
d9ef172
Merge branch 'main' into vraspar/http-wire-scenario
vraspar May 21, 2026
8dfe17b
examples(scenarios): use viem's Hash alias instead of inline template…
vraspar May 21, 2026
b65920e
docs(scenarios): add http-wire-capture entry to README
vraspar May 21, 2026
8143d48
examples: align USDC slot-fallback handling between anvil-setup and h…
vraspar May 21, 2026
fcd24fc
examples(scenarios): assert PaymentAuthorized event paymentInfo/amoun…
vraspar May 21, 2026
1d7137e
examples(scenarios): extract waitForListening helper to dedupe in-pro…
vraspar May 21, 2026
fb2b696
Merge branch 'main' into vraspar/http-wire-scenario
vraspar May 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"scenario:atomic-charge": "tsx scenarios/atomic-charge.ts",
"scenario:partial-refund-flow": "tsx scenarios/partial-refund-flow.ts",
"scenario:permit2-charge": "tsx scenarios/permit2-charge.ts",
"scenario:http-wire-capture": "tsx scenarios/http-wire-capture.ts",
"scenarios:ci": "tsx scripts/scenarios-ci.ts"
},
"dependencies": {
Expand All @@ -27,6 +28,13 @@
"viem": "^2.46.3"
},
"devDependencies": {
"@types/node": "^22.12.0"
"@types/express": "^5.0.0",
"@types/node": "^22.12.0",
"@x402/core": "2.12.0",
"@x402/evm": "2.12.0",
"@x402/express": "2.12.0",
"@x402/fetch": "2.12.0",
"@x402r/evm": "0.2.0-alpha.0",
"express": "^5.0.0"
}
}
16 changes: 16 additions & 0 deletions examples/scenarios/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,20 @@ Demonstrates the atomic settlement path. In production the merchant advertises t

The new authCapture partial-refund pattern. Replaces the old single-tx `refundInEscrow(amount)` with a two-tx flow: merchant captures the amount they keep, then `voidPayment()` returns the remainder to the payer. No allowance setup, no ReceiverRefundCollector — the escrow handles it. Asserts payer net loss equals merchant-keep, receiver delta + fee delta equals merchant-keep.

### permit2-charge

2-role atomic-charge flow routed through Uniswap Permit2 instead of EIP-3009.

Demonstrates the two payer-side moves Permit2 requires: a one-time `ERC20.approve(PERMIT2, MAX)` so the canonical Permit2 contract can pull tokens for any Permit2 spender, then a per-payment `signPermit2Authorization(...)` that the merchant consumes via `payment.charge()`. Asserts payer ↓ amount, receiver Δ + fee Δ === amount, fee Δ > 0.

### http-wire-capture

Cross-package integration test exercising the real HTTP 402 wire end-to-end against an in-process facilitator and resource server.

Boots `@x402/express`'s `paymentMiddleware` + `x402ResourceServer` (with `AuthCaptureServerScheme` from `@x402r/evm/authCapture/server`) on one port, `@x402/core`'s `x402Facilitator` (with `AuthCaptureFacilitatorScheme` from `@x402r/evm/authCapture/facilitator`) on another, and a payer client using `@x402/fetch`'s `wrapFetchWithPayment` + `AuthCaptureEvmScheme` from `@x402r/evm/authCapture/client`. The payer's `fetch` returns HTTP 402, the wrapper signs an authorization, retries, and the facilitator settles on-chain. Asserts the settle tx targets the canonical AuthCaptureEscrow, payer ↓ amount, receiver unchanged (autoCapture left unset), the `PaymentAuthorized` event's `paymentInfo` fields match the resource server's published requirements, and `paymentState(paymentInfoHash)` on the escrow has `hasCollectedPayment === true` and `capturableAmount === amount`.

This is the only scenario that exercises the `@x402/express` ↔ `@x402r/evm` integration seam — wire-format mismatches, scheme registration drift, or signer-interface changes between the upstream packages and `@x402r/evm` surface here and nowhere else in the suite.

## Running

```bash
Expand All @@ -49,6 +63,8 @@ pnpm scenario:capture
pnpm scenario:dispute
pnpm scenario:atomic-charge
pnpm scenario:partial-refund-flow
pnpm scenario:permit2-charge
pnpm scenario:http-wire-capture
```

All scenarios run against a local Anvil fork — no real testnet funds needed.
Loading
Loading