diff --git a/examples/unity-game-x402-gate/.env.example b/examples/unity-game-x402-gate/.env.example index 00a96c7..f4dbfeb 100644 --- a/examples/unity-game-x402-gate/.env.example +++ b/examples/unity-game-x402-gate/.env.example @@ -1,7 +1,8 @@ # Stellar public key (G...) that receives payment. Public — never a secret. X402_SELLER_ADDRESS= -# Free testnet facilitator key: POST https://channels.openzeppelin.com/testnet/gen +# Free testnet facilitator key: GET https://channels.openzeppelin.com/testnet/gen +# (open it in a browser, or `curl`; a POST here returns 401) FACILITATOR_API_KEY= X402_FACILITATOR_URL=https://channels.openzeppelin.com/x402/testnet diff --git a/examples/unity-game-x402-gate/README.md b/examples/unity-game-x402-gate/README.md index 3eea8cd..47b17b2 100644 --- a/examples/unity-game-x402-gate/README.md +++ b/examples/unity-game-x402-gate/README.md @@ -112,7 +112,8 @@ Fill in `.env`: - `X402_SELLER_ADDRESS` — a Stellar **public** key (G...) to receive payment. Public only; no secret involved. - `FACILITATOR_API_KEY` — free testnet key from - `POST https://channels.openzeppelin.com/testnet/gen`. + `GET https://channels.openzeppelin.com/testnet/gen` (open it in a browser, + or `curl`; a `POST` here returns `401 Unauthorized`). - `PLAYER_SECRET_KEY` — only needed for `wallet-bridge-smoke`, a throwaway testnet secret key that will actually pay. **Never use a mainnet key here.** @@ -129,6 +130,13 @@ a payment: Stellar) — this step is reCAPTCHA-gated and has to be done by a human in a browser; there's no API around it. +`X402_SELLER_ADDRESS` needs to be a real account too, not just a valid-looking +key: if you generate a fresh keypair for it (rather than pointing at an +already-funded account), it has to be created on-chain (friendbot) and given +the same USDC trustline above before it can receive the SAC transfer — +otherwise `wallet-bridge-smoke` fails simulation with `HostError: Error(Contract, #13)` +("trustline entry is missing for account"). + ### 2. Run the mocked test suite ```bash diff --git a/examples/unity-game-x402-gate/scripts/wallet-bridge-smoke.ts b/examples/unity-game-x402-gate/scripts/wallet-bridge-smoke.ts index a7a167a..25e757a 100644 --- a/examples/unity-game-x402-gate/scripts/wallet-bridge-smoke.ts +++ b/examples/unity-game-x402-gate/scripts/wallet-bridge-smoke.ts @@ -101,8 +101,11 @@ async function main(): Promise { console.log(`[smoke] payment accepted. Unlocked loot:`); console.log(JSON.stringify(payload.loot, null, 2)); - const txHashHeader = - response.headers.get("x-payment-response") ?? response.headers.get("settlement-response"); + // x402 v2's settlement header is `PAYMENT-RESPONSE`, not the v1 name + // `X-PAYMENT-RESPONSE` (and never `settlement-response`, which isn't a + // real header in either version). See "Settlement Response Delivery" in + // x402-foundation/x402's specs/transports-v2/http.md. + const txHashHeader = response.headers.get("payment-response"); if (txHashHeader) { console.log(`[smoke] settlement response header: ${txHashHeader}`); const decoded = tryDecodeBase64Json(txHashHeader);