Skip to content

README: show direct new CommerceEvmScheme(signer) usage, or clarify class is internal #37

@A1igator

Description

@A1igator

Context

Cold-agent dogfood test: an AI agent with no x402r context was given a merchant URL and a private key, and asked to get a paid response. It found @x402r/evm via the SDK hint in the 402 payload, followed the README, and stumbled on one specific friction point:

The README imports CommerceEvmScheme on line 16:

import { CommerceEvmScheme, registerCommerceEvmScheme } from '@x402r/evm/commerce/client'

…but every example only shows the registerCommerceEvmScheme(client, { signer }) call. The direct class is in scope and never used. By analogy to the register function, the agent tried:

const scheme = new CommerceEvmScheme({ signer: account })

The constructor actually wants the bare account: new CommerceEvmScheme(account). The mismatch throws a misleading error deep inside viem (Address \"undefined\" is invalid), with no indication that the offending parameter is the constructor shape.

What to change

Pick one of:

Option A (preferred): Show the direct constructor form in the README alongside the register helper, so agents who want to skip the register pattern have a correct template:

import { CommerceEvmScheme } from '@x402r/evm/commerce/client'

const scheme = new CommerceEvmScheme(signer)
// pass to whichever client you're using

Option B: Don't import CommerceEvmScheme in README examples if users shouldn't construct it directly. Remove from line 16 import, remove from "Exports" section's top-level @x402r/evm line. Keep it as an internal type.

Option C (mechanical): Make the constructor accept both shapes (new CommerceEvmScheme(signer) and new CommerceEvmScheme({ signer })) and throw a clear error (Expected Account or { signer: Account }, got {signer: undefined}) when neither matches.

Why

This is the only real stumble a cold agent hits on the happy path. Fixing it compresses time-to-first-paid-request materially.

Acceptance criteria

  • README has at least one working, copy-pasteable example of every class/function it imports
  • Misuse produces a clear error message that names the offending parameter (at minimum)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions