Skip to content

fix(examples): wallet-bridge-smoke checks the wrong settlement header - #88

Merged
Eras256 merged 1 commit into
nirium-protocol:mainfrom
M0nsxx:fix/wallet-bridge-smoke-payment-response-header
Sep 19, 2026
Merged

Eras256 merged 1 commit into
nirium-protocol:mainfrom
M0nsxx:fix/wallet-bridge-smoke-payment-response-header

Conversation

@M0nsxx

@M0nsxx M0nsxx commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

What's wrong

Ran examples/unity-game-x402-gate from 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 test passed (3/3, mocked). npm run wallet-bridge-smoke actually settled a real payment on Stellar testnet — server returned the unlocked loot — but printed:

[smoke] no settlement header found on the response — check facilitator/server logs for the settled tx hash.

even though the payment had gone through. Root cause: scripts/wallet-bridge-smoke.ts (lines 104-105) checks response.headers.get("x-payment-response") (x402 v1's header name) and response.headers.get("settlement-response") (not a real header in either version). Neither matches what @x402/express v2 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 a PAYMENT-RESPONSE header. That matches this example's own PAYMENT-SIGNATURE/PAYMENT-REQUIRED naming.

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:

  1. .env.example and README.md say POST https://channels.openzeppelin.com/testnet/gen for the facilitator key. A POST there returns 401 Unauthorized; it's a GET.
  2. The README only says to fund/trustline the player account. If X402_SELLER_ADDRESS is 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 — otherwise wallet-bridge-smoke fails simulation with HostError: Error(Contract, #13) / "trustline entry is missing for account". Added a note.

Evidence this was actually run, not just read

  • Settled testnet tx (post-fix run, script correctly printed this): a7ed5747b475eb29127fde0e347860d3b66cce7accece3de830353b8a194f4ab — successful: true, ledger 4764067.
  • Decoded payment-response header from that run:
    {"success":true,"payer":"GDCCBC35VPNQGDZE3O3GFZAIV6X7JE7HK7V7IJKQJSFOW5CFRCXF4DT5","transaction":"a7ed5747b475eb29127fde0e347860d3b66cce7accece3de830353b8a194f4ab","network":"stellar:testnet"}
  • npm run typecheck and npm test both pass on this branch.

Test plan

  • npm install
  • npm run typecheck
  • npm test (3/3 pass, mocked)
  • npm run wallet-bridge-smoke against real Stellar testnet — settled, loot unlocked, tx hash printed correctly

🤖 Generated with Claude Code

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>
@Eras256
Eras256 merged commit 0a3bd4b into nirium-protocol:main Sep 19, 2026
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