Skip to content

No test drives a real 402 payment loop #423

Closed

Description

@Miracle656

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 maxPrice is 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

  1. gpromise7077-web commented on Oct 17, 2026

    @gpromise7077-web

    @gpromise7077-web has applied to work on this issue as part of the Stellar Wave Program's 10th wave.

    Hi maintainer, I'd like to work on this issue, pls assign me to this task

    ℹ️ Repo Maintainers: To accept this application, review their application or assign @gpromise7077-web to this issue.

  2. GazzyLee commented on Oct 17, 2026

    @GazzyLee
    Contributor

    @GazzyLee has applied to work on this issue as part of the Stellar Wave Program's 10th wave.

    Hello I can get this done for you, please assign

    ℹ️ Repo Maintainers: To accept this application, review their application or assign @GazzyLee to this issue.

  3. lay2lo commented on Oct 17, 2026

    @lay2lo

    @lay2lo has applied to work on this issue as part of the Stellar Wave Program's 10th wave.

    Hi maintainer I’d like to work on this issue

    ℹ️ Repo Maintainers: To accept this application, review their application or assign @lay2lo to this issue.

  4. Ranjeet2063 commented on Oct 17, 2026

    @Ranjeet2063
    Contributor

    @Ranjeet2063 has applied to work on this issue as part of the Stellar Wave Program's 10th wave.

    Ready to ship immediately! Focus: Test Engineering & Automated QA (Vitest / Jest / Cargo Test) for "No test drives a real 402 payment loop". Plan: Construct deterministic unit and integration test suites covering critical boundary invariants and error states. Guaranteed 100% green CI & test coverage. Zero hand-holding. SLA: clean PR in 1-2h. Track record: 166+ merged PRs in Web3 (OSS score 83, Top 2%).

    ℹ️ Repo Maintainers: To accept this application, review their application or assign @Ranjeet2063 to this issue.

  5. Ugasutun commented on Oct 17, 2026

    @Ugasutun
    Contributor

    @Ugasutun has applied to work on this issue as part of the Stellar Wave Program's 10th wave.

    Hi, I'd like to work on this issue. I understand the requirements and can implement the proposed changes while keeping the existing functionality intact. I'll also add the necessary tests, handle relevant edge cases, and verify that the project builds and all tests pass successfully.

    ℹ️ Repo Maintainers: To accept this application, review their application or assign @Ugasutun to this issue.

  6. drips-wave commented on Oct 17, 2026

    @drips-wave

    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 🌊

  7. Miracle656 commented on Oct 25, 2026

    @Miracle656
    CollaboratorAuthor

    Closing as completed, credited to @Ugasutun.

    The work landed in their own PR #487 (commit 94bd8ea), alongside the paid_call allow-list, rather than through #490 — which is why #490's branch was empty once it was rebased. Verified on main rather than taken on trust; tests/x402-paid-call-loop.test.ts, 5 tests, all passing:

    x402 successful payment loop (end to end, stubbed facilitator)
      ✓ drives 402 -> sign -> submit -> resource, verifying what was actually signed
      ✓ refuses to pay when the demanded amount is above maxPrice, without submitting
      ✓ refuses to pay for a network the client is not configured for
      ✓ does not release the resource when the signature is already expired
      ✓ serves the resource through BazaarMcpServer.paid_call once the loop settles
    

    Against the acceptance criteria:

    • End-to-end successful loop against a stub facilitator — yes, and it asserts the resource was reached only after paying (resource.calls.map(c => c.submitted) equals [false, true]), so a stub that returned 200 without a payment would fail.
    • Assert on what was signed, not just the response body — yes, and the comment says exactly why: "Asserting here would fail if the client paid a different amount or a different destination while still returning a body." It checks amount, to, from, credentialAddress and functionName.
    • Network passphrase — this goes further than asked. Rather than asserting the passphrase value, it verifies the signature itself: sigValidOnTestnet true and sigValidOnMainnet false. That proves the signature cannot be replayed against mainnet, which is the thing the passphrase check was a proxy for.
    • Failure branches — all three: above maxPrice (and asserts nothing was submitted), wrong network, already-expired signature.
    • Testnet keys only, generated by the test — Keypair.random() for payer, source and the facilitator's receiving account; nothing committed, no real account.

    The sigValidOnMainnet: false assertion 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.

  8. drips-wave commented on Oct 25, 2026

    @drips-wave

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions