Skip to content

fix(x402): enforce documented payment ceiling - #228

Open
MagMueller wants to merge 1 commit into
mainfrom
agency/x402-payment-cap
Open

MagMueller wants to merge 1 commit into
mainfrom
agency/x402-payment-cap

Conversation

@MagMueller

@MagMueller MagMueller commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • add the documented x402_max_payment_usd and x402MaxPaymentUsd options to the Python and TypeScript V2/V3 clients
  • default SDK-created x402 clients to a $1 per-payment ceiling and reject payment requirements above it
  • cover V1 and V2 payment-requirement shapes, invalid caps, and custom clients
  • correct the x402 guides to state the current V2/V3-only, repeated-payment, wallet-authentication, and free session-management boundaries

Why

The public quickstart already passes these options, but SDK 3.11.1 does not implement them. Python raises TypeError before making a request. TypeScript does not declare the option, and untyped JavaScript ignores it. That means the advertised safety ceiling is not actually registered on SDK-created x402 clients.

This is adjacent to #221 but intentionally narrower. It makes the payment ceiling real and makes the current behavior explicit. It does not add generic wallet authentication, allow existing wallet-keyed credit to bypass a new payment challenge, add V4 x402 support, change the $1 minimum, or change the upto tier.

Validation

  • TypeScript: 147 tests pass
  • TypeScript: type-check and CJS/ESM/declaration builds pass
  • Python: 59 offline tests pass; 22 live or production tests deselected
  • Python: pyright passes with 0 errors and 0 warnings
  • Python: source distribution and wheel builds pass
  • Mintlify broken-link check passes
  • llms.txt generation is idempotent
  • git diff --check passes

No wallet funds, payment, API key, customer data, or live Cloud request was used.


Summary by cubic

Enforces the documented x402MaxPaymentUsd / x402_max_payment_usd option in the Python and TypeScript V2/V3 clients. The option previously had no effect (Python raised TypeError, TypeScript never declared it); SDK-created x402 clients now reject payment requirements above the configured ceiling and default to $1 per payment.

Details

  • Applies to SDK-built clients and custom x402 clients that support policy registration; invalid caps throw RangeError/ValueError.
  • Covers V1 and V2 payment-requirement shapes.
  • Corrects the x402 guides to state the current boundaries: V2/V3 only, every new paid request gets a payment challenge even with unused project credit, and exact session-management calls are free.

Written for commit 0bed23f. Summary will update on new commits.

Review in cubic

@mintlify

mintlify Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
browser-use 🟢 Ready View Preview Aug 27, 2026, 5:10 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 10 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="browser-use-python/src/browser_use_sdk/_core/x402.py">

<violation number="1" location="browser-use-python/src/browser_use_sdk/_core/x402.py:111">
P2: String caps with more than 28 significant digits can round upward during multiplication before `ROUND_FLOOR`, allowing a cap above the requested amount. Scale the decimal exactly or use a precision-sized local decimal context before flooring.</violation>
</file>

<file name="browser-use-node/src/core/x402.ts">

<violation number="1" location="browser-use-node/src/core/x402.ts:50">
P2: For valid decimal caps such as `0.000249`, floating-point multiplication falls just below the intended atomic-unit value, so the ceiling becomes one unit lower than requested. Convert the cap with decimal-safe arithmetic or compensate for representation error before flooring.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

if not amount.is_finite() or amount <= 0:
raise ValueError("x402_max_payment_usd must be a positive finite number")
atomic_units = int(
(amount * _USDC_ATOMIC_UNITS_PER_DOLLAR).to_integral_value(

@cubic-dev-ai cubic-dev-ai Bot Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: String caps with more than 28 significant digits can round upward during multiplication before ROUND_FLOOR, allowing a cap above the requested amount. Scale the decimal exactly or use a precision-sized local decimal context before flooring.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At browser-use-python/src/browser_use_sdk/_core/x402.py, line 111:

<comment>String caps with more than 28 significant digits can round upward during multiplication before `ROUND_FLOOR`, allowing a cap above the requested amount. Scale the decimal exactly or use a precision-sized local decimal context before flooring.</comment>

<file context>
@@ -97,7 +100,43 @@ def _missing_x402() -> ImportError:
+    if not amount.is_finite() or amount <= 0:
+        raise ValueError("x402_max_payment_usd must be a positive finite number")
+    atomic_units = int(
+        (amount * _USDC_ATOMIC_UNITS_PER_DOLLAR).to_integral_value(
+            rounding=ROUND_FLOOR
+        )
</file context>
Fix with cubic

if (!Number.isFinite(maxPaymentUsd) || maxPaymentUsd <= 0) {
throw new RangeError("x402MaxPaymentUsd must be a positive finite number.");
}
const atomicUnits = Math.floor(maxPaymentUsd * USDC_ATOMIC_UNITS_PER_DOLLAR);

@cubic-dev-ai cubic-dev-ai Bot Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: For valid decimal caps such as 0.000249, floating-point multiplication falls just below the intended atomic-unit value, so the ceiling becomes one unit lower than requested. Convert the cap with decimal-safe arithmetic or compensate for representation error before flooring.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At browser-use-node/src/core/x402.ts, line 50:

<comment>For valid decimal caps such as `0.000249`, floating-point multiplication falls just below the intended atomic-unit value, so the ceiling becomes one unit lower than requested. Convert the cap with decimal-safe arithmetic or compensate for representation error before flooring.</comment>

<file context>
@@ -20,13 +20,58 @@ export const X402_BASE_URL_DEFAULT = "https://x402.api.browser-use.com/api/v3";
+  if (!Number.isFinite(maxPaymentUsd) || maxPaymentUsd <= 0) {
+    throw new RangeError("x402MaxPaymentUsd must be a positive finite number.");
+  }
+  const atomicUnits = Math.floor(maxPaymentUsd * USDC_ATOMIC_UNITS_PER_DOLLAR);
+  if (!Number.isSafeInteger(atomicUnits) || atomicUnits < 1) {
+    throw new RangeError("x402MaxPaymentUsd must resolve to at least one USDC atomic unit.");
</file context>
Suggested change
const atomicUnits = Math.floor(maxPaymentUsd * USDC_ATOMIC_UNITS_PER_DOLLAR);
const atomicUnits = Math.floor(
maxPaymentUsd * USDC_ATOMIC_UNITS_PER_DOLLAR +
Number.EPSILON * Math.max(1, Math.abs(maxPaymentUsd * USDC_ATOMIC_UNITS_PER_DOLLAR)),
);
Fix with cubic

@danrasmuson

Copy link
Copy Markdown

I'm interested in building x402 integration for my users with browser use. If this gets merged and fixes the top off issue before I get some other integration in place I'd love to use it.

This branch was successfully deployed

1 active deployment
staging - docs — 0bed23fe Deployed Aug 27, 2026 by mintlify[bot]
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