Repository navigation
No test drives a real 402 payment loop #423
Description
Background
The 402 test asserts that a rejected payment maps to ERR_PAYMENT_REJECTED.
Nothing tests the path where a 402 is answered successfully: the payment is
constructed, signed, submitted and the resource returned.
That path is the reason this tool exists, it is the one that moves money, and it
is the one that would break silently on an x402 or Stellar SDK upgrade — which
is not hypothetical, since this repo currently pins @stellar/stellar-sdk at a
major four behind current.
What to build
- An end-to-end test of the successful 402 loop against a stubbed resource that
demands payment and verifies it — a fake facilitator, not mainnet. - Assert on what was signed: amount, destination, network passphrase. A test that
only checks the response body would pass while paying the wrong account. - Cover the failure branches too: wrong network, expired signature, amount above
maxPrice. - Testnet keys only, generated by the test, never committed and never a real
account.
Acceptance criteria
- A successful 402 loop is tested end to end against a stub
- Assertions cover amount, destination and network, not just the response
- Payment above
maxPriceis refused, asserted - No real key or mainnet account is used
- The test is deterministic and needs no network access
Drips Wave · Complexity: Advanced · 200 points
Repo: Divinity-Labs/Lens. The MCP server is src/mcp/server.ts
(BazaarMcpServer) with error codes in src/mcp/codes.ts. It is started by
npm run mcp:server → examples/mcp-server/run.ts, and there is an agent
example at examples/mcp-server/agent.ts. Tests are tests/mcp.test.ts.
Run the tests: npm test. The tests are vitest, not jest. A single file
is npx vitest run tests/mcp.test.ts.
Load test (prices) is already failing on main. Not your PR.
This surface signs with a real mainnet key. examples/mcp-server/run.ts
requires MCP_AGENT_SECRET_KEY_MAINNET and builds a signer for
stellar:pubnet. Anything you change here can move real money, so prefer
failing closed, and never log, echo or test with a real secret key.
Never elide an address, a contract id or a key in code, comments or
fixtures. A previous batch shortened a contract id and five contributors
invented plausible-looking ids to fill the gap. Write it in full or not at all.
An agent is the least able caller to notice a wrong answer. It will reason
over whatever it is handed, confidently. Prefer a structured error over a
best-effort result.
Required: Before submitting, join the contributor Telegram so your work can be tracked and counted toward the Stellar Wave: https://t.me/+fxHXq8f1SwlkZDBk
Activity
gpromise7077-web commentedon Oct 17, 2026
@gpromise7077-web has applied to work on this issue as part of the Stellar Wave Program's 10th wave.
ℹ️ Repo Maintainers: To accept this application, review their application or assign @gpromise7077-web to this issue.
GazzyLee commentedon Oct 17, 2026
@GazzyLee has applied to work on this issue as part of the Stellar Wave Program's 10th wave.
ℹ️ Repo Maintainers: To accept this application, review their application or assign @GazzyLee to this issue.
lay2lo commentedon Oct 17, 2026
@lay2lo has applied to work on this issue as part of the Stellar Wave Program's 10th wave.
ℹ️ Repo Maintainers: To accept this application, review their application or assign @lay2lo to this issue.
Ranjeet2063 commentedon Oct 17, 2026
@Ranjeet2063 has applied to work on this issue as part of the Stellar Wave Program's 10th wave.
ℹ️ Repo Maintainers: To accept this application, review their application or assign @Ranjeet2063 to this issue.
Ugasutun commentedon Oct 17, 2026
@Ugasutun has applied to work on this issue as part of the Stellar Wave Program's 10th wave.
ℹ️ Repo Maintainers: To accept this application, review their application or assign @Ugasutun to this issue.
drips-wave commentedon Oct 17, 2026
Congratulations, @Ugasutun! 🎉 Your application was accepted by the repo's maintainers, and the issue is due on October 22, 2026.
🧑💻 @Ugasutun: Please resolve the issue such that the repo's maintainers have enough time to review your contribution before the due date. You'll earn Points for completing the issue on-time, which will make you eligible for a share of the Stellar Wave Program's reward pool.
Warning
When opening a PR, please link it to this issue to ensure it gets tracked accurately. Points are awarded when this issue is marked as completed by the maintainer.
🤠 Repo maintainers: Please keep an eye on the contributor's progress and review their work before the due date. You can manage this issue, including adjusting its complexity and points, here.
🌊 Happy Wave 🌊
test(x402): drive the successful 402 payment loop end to end (Divinit…
feat: add configurable host allow-list to paid_call, refuse before an…
feat: add lens_get_price tool returning aggregated pair price with is…
Miracle656 commentedon Oct 25, 2026
Closing as completed, credited to @Ugasutun.
The work landed in their own PR #487 (commit
94bd8ea), alongside thepaid_callallow-list, rather than through #490 — which is why #490's branch was empty once it was rebased. Verified onmainrather than taken on trust;tests/x402-paid-call-loop.test.ts, 5 tests, all passing:Against the acceptance criteria:
resource.calls.map(c => c.submitted)equals[false, true]), so a stub that returned 200 without a payment would fail.amount,to,from,credentialAddressandfunctionName.sigValidOnTestnettrue andsigValidOnMainnetfalse. That proves the signature cannot be replayed against mainnet, which is the thing the passphrase check was a proxy for.maxPrice(and asserts nothing was submitted), wrong network, already-expired signature.Keypair.random()for payer, source and the facilitator's receiving account; nothing committed, no real account.The
sigValidOnMainnet: falseassertion is the one I'd single out. A signature that verifies on both networks is a live cross-network replay, and this is the only test in the repo that rules it out.drips-wave commentedon Oct 25, 2026
This issue has been completed by @Ugasutun as part of the Stellar Wave Program's 10th Wave 🥳
😎 @Ugasutun: You earned 200 Points for completing this issue! Once the Wave's rewards are finalized, you'll be eligible for a percentage of the Wave's reward pool based on the percentage of total points you've earned. Learn more here. You can also Leave a review to share your experience working on this issue.
🧑💻 Repo maintainers: How'd the contributor do? Leave a review to share your experience working with them.