fix(examples): wallet-bridge-smoke checks the wrong settlement header - #88
Merged
Eras256 merged 1 commit intoSep 19, 2026
Conversation
scripts/wallet-bridge-smoke.ts looked for x-payment-response (x402 v1's header name) or settlement-response (not a real header in either version), so it always fell through to "no settlement header found" even after a real payment settled. x402 v2 sends it as PAYMENT-RESPONSE — confirmed against x402-foundation/x402's specs/transports-v2/http.md, "Settlement Response Delivery" section, and against the actual header captured off a live testnet run. Also documents two things a from-scratch run surfaces that the README didn't cover: the facilitator key endpoint is GET, not POST (POST returns 401), and X402_SELLER_ADDRESS needs to be a real funded account with a USDC trustline if you generate a fresh keypair for it rather than reusing an existing one — otherwise the Soroban simulation fails with HostError: Error(Contract, nirium-protocol#13). Verified end to end against Stellar testnet with fresh throwaway keypairs: settled tx a7ed5747b475eb29127fde0e347860d3b66cce7accece3de830353b8a194f4ab (https://stellar.expert/explorer/testnet/tx/a7ed5747b475eb29127fde0e347860d3b66cce7accece3de830353b8a194f4ab), payment-response header decodes to {"success":true,"payer":"GDCCBC35VPNQGDZE3O3GFZAIV6X7JE7HK7V7IJKQJSFOW5CFRCXF4DT5","transaction":"a7ed5747...","network":"stellar:testnet"}. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.
What's wrong
Ran
examples/unity-game-x402-gatefrom scratch on my own machine (fresh clone, own testnet keypairs, own OpenZeppelin Channels testnet facilitator key) to independently verify it before a HackMeridian Lisboa demo.npm testpassed (3/3, mocked).npm run wallet-bridge-smokeactually settled a real payment on Stellar testnet — server returned the unlocked loot — but printed:even though the payment had gone through. Root cause:
scripts/wallet-bridge-smoke.ts(lines 104-105) checksresponse.headers.get("x-payment-response")(x402 v1's header name) andresponse.headers.get("settlement-response")(not a real header in either version). Neither matches what@x402/expressv2 actually sends.Confirmed against the spec, not just my own run:
specs/transports-v2/http.md, section "Settlement Response Delivery", states the server sends settlement results in aPAYMENT-RESPONSEheader. That matches this example's ownPAYMENT-SIGNATURE/PAYMENT-REQUIREDnaming.The fix
response.headers.get("payment-response")(header lookups are case-insensitive). One-line change, comment cites the spec section.Two doc gaps found along the way
Both cost me real time on a from-scratch run, so I fixed them rather than filing separately:
.env.exampleandREADME.mdsayPOST https://channels.openzeppelin.com/testnet/genfor the facilitator key. APOSTthere returns401 Unauthorized; it's aGET.X402_SELLER_ADDRESSis a freshly generated keypair (as opposed to pointing at an already-funded account), it also needs to exist on-chain and hold the USDC trustline before it can receive the SAC transfer — otherwisewallet-bridge-smokefails simulation withHostError: Error(Contract, #13)/"trustline entry is missing for account". Added a note.Evidence this was actually run, not just read
a7ed5747b475eb29127fde0e347860d3b66cce7accece3de830353b8a194f4ab—successful: true, ledger 4764067.payment-responseheader from that run:{"success":true,"payer":"GDCCBC35VPNQGDZE3O3GFZAIV6X7JE7HK7V7IJKQJSFOW5CFRCXF4DT5","transaction":"a7ed5747b475eb29127fde0e347860d3b66cce7accece3de830353b8a194f4ab","network":"stellar:testnet"}npm run typecheckandnpm testboth pass on this branch.Test plan
npm installnpm run typechecknpm test(3/3 pass, mocked)npm run wallet-bridge-smokeagainst real Stellar testnet — settled, loot unlocked, tx hash printed correctly🤖 Generated with Claude Code