feat: facilitator#1
Conversation
📝 WalkthroughWalkthroughAdded two example apps (client and server) demonstrating x402 payment flows, and a new Cloudflare Worker package ( Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Server
participant Facilitator
participant ZeroG_RPC
Client->>Server: GET /weather (wrapped fetch triggers payment)
Server->>Facilitator: validate/require payment (middleware calls X402_FACILITATOR)
Facilitator->>ZeroG_RPC: sign/verify/settle txs / read chain state
ZeroG_RPC-->>Facilitator: tx result / proof
Facilitator-->>Server: verification/settlement result
Server-->>Client: 200 with payment-settle headers and JSON body
Client->>Client: extract payment settlement from headers (x402 client)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
🧹 Nitpick comments (8)
examples/client/package.json (1)
7-7: Avoid using "latest" for better build reproducibility.Using
"latest"for@types/bunprevents reproducible builds and may introduce breaking changes unexpectedly. Pin to a specific version or use a version range instead.♻️ Recommended fix
"devDependencies": { - "@types/bun": "latest" + "@types/bun": "^1.3.12"Alternatively, reference the workspace catalog (if this package is added to the workspace):
"devDependencies": { - "@types/bun": "latest" + "@types/bun": "catalog:"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/client/package.json` at line 7, The dependency entry for "@types/bun" in package.json is pinned to "latest", which breaks reproducible builds; update the dependency value from "latest" to a specific version or a constrained semver range (e.g., "0.x" or "0.1.2") in the dependencies/devDependencies block so the package.json (and any workspace reference) uses a fixed, tested version instead of "latest".examples/client/.gitignore (1)
16-16: Unusual glob pattern for report files.The pattern
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.jsonmatches filenames with underscores after each digit (e.g.,report.1_.2_.3_.4_.json), which is uncommon. If you intend to match typical versioned reports likereport.1.2.3.4.json, consider using a wildcard pattern instead.♻️ Alternative pattern
# logs logs _.log -report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json +report.*.jsonOr if you need digit matching:
-report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/client/.gitignore` at line 16, The glob pattern "report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json" is incorrect (it expects underscores after each digit); replace it with a pattern that matches versioned report files, e.g. use "report.*.*.*.*.json" to match any dotted segments or "report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json" to restrict to numeric segments, updating the existing line containing "report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json".packages/facilitator/src/lib/chains/0g.ts (1)
13-16: Use computed keys to avoid network-id drift.The mapping duplicates literal network IDs that already exist as constants. Prefer computed keys so a future chain-id change can’t desync this object.
♻️ Proposed refactor
export const ZERO_GRAVITY_CHAIN_MAPPING = { - "eip155:16661": zeroGMainnet, - "eip155:16602": zeroGTestnet, + [zeroGMainnetNetworkId]: zeroGMainnet, + [zeroGTestnetNetworkId]: zeroGTestnet, } satisfies Record<ZeroGChain, Chain>;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/facilitator/src/lib/chains/0g.ts` around lines 13 - 16, The mapping ZERO_GRAVITY_CHAIN_MAPPING uses hard-coded network ID strings; change the object keys to computed keys that derive from the canonical ZeroG chain id constants/enum instead of literal strings so they can’t drift (e.g., replace "eip155:16661" and "eip155:16602" with computed property keys built from the existing ZeroGChain/chain id constants such as [`eip155:${ZeroGChain.MAINNET}`] and [`eip155:${ZeroGChain.TESTNET}`] or the corresponding numeric constants, while keeping the values zeroGMainnet and zeroGTestnet and the satisfies Record<ZeroGChain, Chain> assertion).packages/facilitator/wrangler.jsonc (1)
7-10: Consider making sampling rate environment-specific.
head_sampling_rate: 0.1is fine to start, but making it env-dependent (dev/staging/prod) helps control telemetry cost as traffic grows.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/facilitator/wrangler.jsonc` around lines 7 - 10, The fixed value for observability.head_sampling_rate should be made environment-specific: update the configuration around the "observability" object to read a per-environment override (e.g., an env var like OBSERVABILITY_HEAD_SAMPLING_RATE or per-environment sections used by wrangler) and fall back to 0.1 if not provided; change the "head_sampling_rate" key to reference that env/config value so dev/staging/prod can each set lower/higher sampling without editing the file directly (look for the "observability" object and the "head_sampling_rate" key to implement this).packages/facilitator/src/env.ts (1)
1-8: Consider adding an explicit reference toCloudflareBindingsfor defensive clarity.
Envcurrently relies on TypeScript's default.d.tsfile discovery, which works fine with the current tsconfig. However, if the generated declaration is ever excluded in a future CI/package context, the type would be missing. Adding an explicit/// <reference>comment makes the dependency unambiguous.♻️ Optional explicit reference
+/// <reference path="../worker-configuration.d.ts" /> import type { X402FacilitatorClientVariables } from "./middlewares/x402-facilitator-client";🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/facilitator/src/env.ts` around lines 1 - 8, Add an explicit triple-slash reference to the Cloudflare types so the Env interface does not implicitly depend on ambient discovery: add a top-level reference comment that points to the Cloudflare types (so CloudflareBindings is unambiguous) above the existing imports; ensure the file still exports Variables and Env (referencing the existing Variables and CloudflareBindings symbols) and that no other code changes are required.examples/server/package.json (1)
6-8: Pin@types/bunto a specific version instead of"latest".Using a floating version in
package.jsoncan cause non-deterministic type behavior, especially if the lockfile is regenerated or removed. Even with lockfiles providing determinism, pinning directly inpackage.jsonis a best practice. The project appears to use workspace catalogs; consider adding an entry for@types/bunin the catalog or pinning to a fixed version (e.g.,"1.3.12").🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/server/package.json` around lines 6 - 8, Update the devDependency entry for `@types/bun` in package.json to use a fixed, specific version (e.g., "1.3.12") instead of "latest" to avoid non-deterministic type changes; locate the "devDependencies" object and change the "@types/bun" value accordingly or add a pinned entry for `@types/bun` to the workspace catalog if you prefer central management.packages/facilitator/src/lib/x402/scheme.ts (1)
17-20: Remove stale commented registration paths.Keeping
registerV1(...)commented blocks here makes the intended registration contract ambiguous and invites drift during future edits.Suggested cleanup
export const registerZeroGExactScheme = ( facilitator: x402Facilitator, chain: ZeroGChain, signer: FacilitatorEvmSigner ) => { facilitator.register( chain, new ExactEvmScheme(signer, { deployERC4337WithEIP6492: true }) ); - // facilitator.registerV1( - // chain, - // new ExactEvmScheme(signer, { deployERC4337WithEIP6492: true }) - // ); }; @@ export const registerZeroGUptoScheme = ( facilitator: x402Facilitator, chain: ZeroGChain, signer: FacilitatorEvmSigner ) => { facilitator.register(chain, new UptoEvmScheme(signer)); - // facilitator.registerV1(chain, new UptoEvmScheme(signer)); };Also applies to: 29-29
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/facilitator/src/lib/x402/scheme.ts` around lines 17 - 20, Remove the stale commented registration calls so the codebase doesn't retain ambiguous, dead registration paths: delete the commented facilitator.registerV1(...) blocks that reference ExactEvmScheme (including the variant with deployERC4337WithEIP6492) at the indicated spots (the commented block around registerV1/ExactEvmScheme and the second commented line at 29) so only the active registration code remains; ensure no other commented registerV1 usages are left in this file to avoid future drift.packages/facilitator/src/middlewares/x402-facilitator-client.ts (1)
22-64: Cache the facilitator and signers outside the request handler to avoid per-request reconstruction.The middleware re-initializes and re-registers the facilitator, clients, signers, and schemes for every incoming request. Since
x402FacilitatorClient()is instantiated once during app setup, move the client and signer initialization outside the async callback so they're created once and reused across all requests.export const x402FacilitatorClient = () => { const facilitator = new x402Facilitator(); const signer = privateKeyToAccount(c.env.FACILITATOR_PRIVATE_KEY as Hex); // ... initialize clients and register schemes once ... return createMiddleware<Env>(async (c, next) => { // Reuse cached instances await next(); }); };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/facilitator/src/middlewares/x402-facilitator-client.ts` around lines 22 - 64, The middleware currently constructs x402Facilitator, signer and wallet clients and re-registers schemes on every request; move the one-time initialization out of the async request handler in x402FacilitatorClient so these are created once and reused: instantiate x402Facilitator, call privateKeyToAccount with FACILITATOR_PRIVATE_KEY, createZeroGWalletClient for zeroGMainnetNetworkId and zeroGTestnetNetworkId, createZeroGFacilitatorSigner for each client, and call registerZeroGExactScheme/registerZeroGUptoScheme during middleware creation (before calling createMiddleware), then inside the returned async (c, next) handler attach the ready facilitator/signers to the request context (for example c.state or c.locals) and simply await next(); this prevents per-request reconstruction while preserving access to the initialized instances.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@examples/client/index.ts`:
- Around line 7-9: The code currently force-casts process.env.EVM_PRIVATE_KEY
into `0x${string}` and passes it directly to privateKeyToAccount, which will
crash with an unclear error if the env var is missing/invalid; add an explicit
guard before calling privateKeyToAccount: read process.env.EVM_PRIVATE_KEY into
a variable, verify it exists (and optionally normalize/validate that it starts
with "0x" and has the expected length for a 32-byte key), and throw a clear
Error (or exit) with a helpful message if it's absent/invalid; then pass the
validated/normalized value to privateKeyToAccount to create signer.
In `@examples/client/package.json`:
- Around line 9-10: Update the peer dependency declaration so the package
accepts TypeScript 6 to match the workspace catalog: change the
peerDependencies.typescript entry in examples/client/package.json from "^5" to a
range that includes 6 (for example "^6" or ">=6.0.2"), ensuring the peer
dependency range aligns with the workspace TypeScript version.
In `@examples/server/index.ts`:
- Around line 8-12: Replace the hardcoded unsafe example values with validated
runtime configuration: read and validate the on-chain recipient into the
variable evmAddress (used as payTo) from env/config and ensure it is a
well-formed EVM address before use, and construct HTTPFacilitatorClient using a
secure, validated facilitator URL (prefer https and validate the origin) pulled
from runtime config; add explicit validation/error handling around evmAddress
and the URL (e.g., in initialization or a validateConfig helper) so the example
fails fast with a clear message if payTo or facilitator URL are missing or
invalid.
- Around line 18-23: The conversion to token units using Math.floor(amount *
1_000_000).toString() does not validate the input; guard the input `amount` in
the async handler (the arrow function taking (amount: number, _network: string))
by checking Number.isFinite(amount) and amount > 0 (and optionally
!Number.isNaN(amount)); if the check fails return an appropriate error/throw or
a rejected response instead of computing `tokenAmount`, ensuring you do not
produce invalid token strings.
In `@packages/facilitator/.env.example`:
- Around line 2-3: Rename the non-standard env vars that start with a digit
(0G_MAINNET_RPC_URL, 0G_TESTNET_RPC_URL) to identifiers that start with a letter
or underscore (for example OG_MAINNET_RPC_URL and OG_TESTNET_RPC_URL) by
updating .env.example and every code reference; update the TypeScript
declaration worker-configuration.d.ts and the middleware
x402-facilitator-client.ts to use the new names, and replace bracket-access
patterns like c.env["0G_MAINNET_RPC_URL"] with the new identifier access
(c.env.OG_MAINNET_RPC_URL or c.env["OG_MAINNET_RPC_URL"]) so all usages compile
and runtime env lookups still work.
In `@packages/facilitator/src/handlers/settle.ts`:
- Line 42: Remove the direct logging of the full settleResponse in
handlers/settle.ts (the console.log({ settleResponse }) call) because it can
leak payment/signature metadata; either delete that line or replace it with a
sanitized log that only includes safe fields (e.g., status, transactionId) or
use a debug-level logger (e.g., processLogger.debug) after stripping sensitive
fields before logging. Ensure you reference the settleResponse variable in your
change so the handler (settle.ts) no longer emits raw settlement objects on the
request path.
- Around line 20-26: The handler currently returns validation errors with HTTP
200 by calling c.json(...) on failures; update both failure branches (the check
of resolvedPaymentPayload.success and the check of
resolvedPaymentRequirements.success after parsePaymentRequirements) to return a
4xx status (e.g., use c.status(400).json(...) or c.status(422).json(...))
instead of c.json(...). Ensure you change both the resolvedPaymentPayload
rejection path and the resolvedPaymentRequirements rejection path so clients
receive an appropriate client-error status code.
In `@packages/facilitator/src/handlers/supported.ts`:
- Around line 11-13: Replace the raw console.error(err) in the catch block
inside the payment-path handler (supported.ts) with structured, sanitized
logging: capture only safe scalar fields (e.g., err.message, err.code) and
relevant safe context (e.g., paymentId or requestId from the handler) and omit
full error objects/stacks; ideally call a dedicated helper like
sanitizeError(err) before logging and use the module logger (e.g., logger.error)
with a descriptive message and the sanitized fields rather than printing the raw
err.
In `@packages/facilitator/src/handlers/verify.ts`:
- Around line 20-26: The handlers currently return validation errors with a 200
status because they call c.json(...) directly; update both validation failure
paths that check resolvedPaymentPayload.success and
resolvedPaymentRequirements.success to return a client error status (e.g., use
c.status(400).json(...) or c.status(422).json(...)) instead of c.json(...).
Specifically, change the return behavior where parsePaymentRequirements(...) and
the payment payload resolution (resolvedPaymentPayload) are inspected so the
response uses c.status(400).json(resolvedPaymentPayload.error) and
c.status(400).json(resolvedPaymentRequirements.error) (or 422 if you prefer) to
signal a 4xx validation failure to clients.
In `@packages/facilitator/src/middlewares/x402-facilitator-client.ts`:
- Around line 26-36: The middleware initializes clients with unvalidated env
vars causing cryptic runtime errors; before calling privateKeyToAccount and
createZeroGWalletClient, validate that process/env FACILITATOR_PRIVATE_KEY
exists and matches the expected hex pattern/length (and normalize prefix if
needed), wrap the privateKeyToAccount call in a try/catch to rethrow a clear
error referencing FACILITATOR_PRIVATE_KEY and privateKeyToAccount, and validate
0G_MAINNET_RPC_URL and 0G_TESTNET_RPC_URL by parsing them with the URL
constructor (or simple regex) and throw clear errors naming the offending env
var; perform these checks prior to creating mainnetClient/testnetClient
(references: privateKeyToAccount, createZeroGWalletClient,
FACILITATOR_PRIVATE_KEY, 0G_MAINNET_RPC_URL, 0G_TESTNET_RPC_URL,
zeroGMainnetNetworkId, zeroGTestnetNetworkId).
---
Nitpick comments:
In `@examples/client/.gitignore`:
- Line 16: The glob pattern "report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json" is
incorrect (it expects underscores after each digit); replace it with a pattern
that matches versioned report files, e.g. use "report.*.*.*.*.json" to match any
dotted segments or "report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json" to restrict to
numeric segments, updating the existing line containing
"report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json".
In `@examples/client/package.json`:
- Line 7: The dependency entry for "@types/bun" in package.json is pinned to
"latest", which breaks reproducible builds; update the dependency value from
"latest" to a specific version or a constrained semver range (e.g., "0.x" or
"0.1.2") in the dependencies/devDependencies block so the package.json (and any
workspace reference) uses a fixed, tested version instead of "latest".
In `@examples/server/package.json`:
- Around line 6-8: Update the devDependency entry for `@types/bun` in package.json
to use a fixed, specific version (e.g., "1.3.12") instead of "latest" to avoid
non-deterministic type changes; locate the "devDependencies" object and change
the "@types/bun" value accordingly or add a pinned entry for `@types/bun` to the
workspace catalog if you prefer central management.
In `@packages/facilitator/src/env.ts`:
- Around line 1-8: Add an explicit triple-slash reference to the Cloudflare
types so the Env interface does not implicitly depend on ambient discovery: add
a top-level reference comment that points to the Cloudflare types (so
CloudflareBindings is unambiguous) above the existing imports; ensure the file
still exports Variables and Env (referencing the existing Variables and
CloudflareBindings symbols) and that no other code changes are required.
In `@packages/facilitator/src/lib/chains/0g.ts`:
- Around line 13-16: The mapping ZERO_GRAVITY_CHAIN_MAPPING uses hard-coded
network ID strings; change the object keys to computed keys that derive from the
canonical ZeroG chain id constants/enum instead of literal strings so they can’t
drift (e.g., replace "eip155:16661" and "eip155:16602" with computed property
keys built from the existing ZeroGChain/chain id constants such as
[`eip155:${ZeroGChain.MAINNET}`] and [`eip155:${ZeroGChain.TESTNET}`] or the
corresponding numeric constants, while keeping the values zeroGMainnet and
zeroGTestnet and the satisfies Record<ZeroGChain, Chain> assertion).
In `@packages/facilitator/src/lib/x402/scheme.ts`:
- Around line 17-20: Remove the stale commented registration calls so the
codebase doesn't retain ambiguous, dead registration paths: delete the commented
facilitator.registerV1(...) blocks that reference ExactEvmScheme (including the
variant with deployERC4337WithEIP6492) at the indicated spots (the commented
block around registerV1/ExactEvmScheme and the second commented line at 29) so
only the active registration code remains; ensure no other commented registerV1
usages are left in this file to avoid future drift.
In `@packages/facilitator/src/middlewares/x402-facilitator-client.ts`:
- Around line 22-64: The middleware currently constructs x402Facilitator, signer
and wallet clients and re-registers schemes on every request; move the one-time
initialization out of the async request handler in x402FacilitatorClient so
these are created once and reused: instantiate x402Facilitator, call
privateKeyToAccount with FACILITATOR_PRIVATE_KEY, createZeroGWalletClient for
zeroGMainnetNetworkId and zeroGTestnetNetworkId, createZeroGFacilitatorSigner
for each client, and call registerZeroGExactScheme/registerZeroGUptoScheme
during middleware creation (before calling createMiddleware), then inside the
returned async (c, next) handler attach the ready facilitator/signers to the
request context (for example c.state or c.locals) and simply await next(); this
prevents per-request reconstruction while preserving access to the initialized
instances.
In `@packages/facilitator/wrangler.jsonc`:
- Around line 7-10: The fixed value for observability.head_sampling_rate should
be made environment-specific: update the configuration around the
"observability" object to read a per-environment override (e.g., an env var like
OBSERVABILITY_HEAD_SAMPLING_RATE or per-environment sections used by wrangler)
and fall back to 0.1 if not provided; change the "head_sampling_rate" key to
reference that env/config value so dev/staging/prod can each set lower/higher
sampling without editing the file directly (look for the "observability" object
and the "head_sampling_rate" key to implement this).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 22970419-ab89-46ef-bf8d-f9bef90e7176
⛔ Files ignored due to path filters (3)
bun.lockis excluded by!**/*.lockexamples/client/bun.lockis excluded by!**/*.lockexamples/server/bun.lockis excluded by!**/*.lock
📒 Files selected for processing (28)
examples/client/.env.exampleexamples/client/.gitignoreexamples/client/index.tsexamples/client/package.jsonexamples/client/tsconfig.jsonexamples/server/.gitignoreexamples/server/index.tsexamples/server/package.jsonexamples/server/tsconfig.jsonpackage.jsonpackages/facilitator/.env.examplepackages/facilitator/.gitignorepackages/facilitator/biome.jsonpackages/facilitator/package.jsonpackages/facilitator/src/env.tspackages/facilitator/src/errors.tspackages/facilitator/src/handlers/settle.tspackages/facilitator/src/handlers/supported.tspackages/facilitator/src/handlers/verify.tspackages/facilitator/src/index.tspackages/facilitator/src/lib/chains/0g.tspackages/facilitator/src/lib/x402/scheme.tspackages/facilitator/src/lib/x402/signer.tspackages/facilitator/src/middlewares/x402-facilitator-client.tspackages/facilitator/tsconfig.jsonpackages/facilitator/vitest.config.tspackages/facilitator/worker-configuration.d.tspackages/facilitator/wrangler.jsonc
There was a problem hiding this comment.
♻️ Duplicate comments (1)
packages/facilitator/src/middlewares/x402-facilitator-client.ts (1)
26-36:⚠️ Potential issue | 🟠 MajorAdd runtime env validation before constructing signer/clients.
as Hexis compile-time only; invalid or missing bindings can still fail at runtime with unclear errors in the request path. Please validateFACILITATOR_PRIVATE_KEY,ZEROG_MAINNET_RPC_URL, andZEROG_TESTNET_RPC_URLbefore callingprivateKeyToAccount/createZeroGWalletClient.Proposed hardening
export const x402FacilitatorClient = () => createMiddleware<Env>(async (c, next) => { const facilitator = new x402Facilitator(); - const signer = privateKeyToAccount(c.env.FACILITATOR_PRIVATE_KEY as Hex); + const privateKey = c.env.FACILITATOR_PRIVATE_KEY; + if (!/^0x[a-fA-F0-9]{64}$/.test(privateKey)) { + throw new Error("Invalid FACILITATOR_PRIVATE_KEY: expected 0x + 64 hex chars"); + } + try { + privateKeyToAccount(privateKey as Hex); + } catch { + throw new Error("Invalid FACILITATOR_PRIVATE_KEY for privateKeyToAccount"); + } + for (const [name, value] of [ + ["ZEROG_MAINNET_RPC_URL", c.env.ZEROG_MAINNET_RPC_URL], + ["ZEROG_TESTNET_RPC_URL", c.env.ZEROG_TESTNET_RPC_URL], + ] as const) { + try { + new URL(value); + } catch { + throw new Error(`Invalid ${name}: must be a valid URL`); + } + } + const signer = privateKeyToAccount(privateKey as Hex); const mainnetClient = createZeroGWalletClient( zeroGMainnetNetworkId, c.env.ZEROG_MAINNET_RPC_URL, signer );According to the current viem docs, what runtime validation/error behavior does privateKeyToAccount apply to malformed hex private keys?🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/facilitator/src/middlewares/x402-facilitator-client.ts` around lines 26 - 36, Validate the FACILITATOR_PRIVATE_KEY, ZEROG_MAINNET_RPC_URL, and ZEROG_TESTNET_RPC_URL environment values at runtime before calling privateKeyToAccount or createZeroGWalletClient: check that FACILITATOR_PRIVATE_KEY is present and a valid hex string (and reject/throw a clear error if not), and that ZEROG_MAINNET_RPC_URL and ZEROG_TESTNET_RPC_URL are non-empty valid URLs; perform these checks in the middleware initialization (before calling privateKeyToAccount and createZeroGWalletClient) and surface a descriptive error/log if validation fails so signer/client construction won’t produce unclear runtime failures.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@packages/facilitator/src/middlewares/x402-facilitator-client.ts`:
- Around line 26-36: Validate the FACILITATOR_PRIVATE_KEY,
ZEROG_MAINNET_RPC_URL, and ZEROG_TESTNET_RPC_URL environment values at runtime
before calling privateKeyToAccount or createZeroGWalletClient: check that
FACILITATOR_PRIVATE_KEY is present and a valid hex string (and reject/throw a
clear error if not), and that ZEROG_MAINNET_RPC_URL and ZEROG_TESTNET_RPC_URL
are non-empty valid URLs; perform these checks in the middleware initialization
(before calling privateKeyToAccount and createZeroGWalletClient) and surface a
descriptive error/log if validation fails so signer/client construction won’t
produce unclear runtime failures.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: e4b1a523-a838-417b-ad36-eead21dafa1c
📒 Files selected for processing (6)
packages/facilitator/.env.examplepackages/facilitator/src/handlers/settle.tspackages/facilitator/src/handlers/supported.tspackages/facilitator/src/handlers/verify.tspackages/facilitator/src/middlewares/x402-facilitator-client.tspackages/facilitator/worker-configuration.d.ts
✅ Files skipped from review due to trivial changes (1)
- packages/facilitator/.env.example
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/facilitator/src/handlers/supported.ts
- packages/facilitator/src/handlers/verify.ts
Summary by CodeRabbit
New Features
Chores