Skip to content

Integrate Starknet facilitator-server coverage and validation#42

Open
welttowelt wants to merge 3 commits intodaydreamsai:mainfrom
welttowelt:codex/issue-41-starknet-facilitator-server
Open

Integrate Starknet facilitator-server coverage and validation#42
welttowelt wants to merge 3 commits intodaydreamsai:mainfrom
welttowelt:codex/issue-41-starknet-facilitator-server

Conversation

@welttowelt
Copy link

@welttowelt welttowelt commented Feb 21, 2026

Summary

  • add explicit facilitator-server Starknet /supported tests for kinds, metadata, signer list, and canonical CAIP/x402 v2 behavior
  • add Starknet config validation tests for missing sponsor fail-fast and unresolved RPC/paymaster skip behavior
  • extend facilitator-server e2e CI script to boot with deterministic Starknet env and assert Starknet appears in /supported
  • document Starknet facilitator-server env vars and add opt-in local run guidance

Testing

  • cd examples/facilitator-server && bun run test
  • cd examples/facilitator-server && bun run build
  • cd examples/facilitator-server && DATABASE_URL=postgresql://facilitator:facilitator@localhost:5432/facilitator bun run test:e2e

Closes #41

Summary by CodeRabbit

  • New Features

    • Opt-in Starknet network support with per-network RPC, paymaster endpoint, API key, and sponsor address
  • Documentation

    • Added Starknet setup docs, examples, and an optional commented docker-compose snippet (disabled by default)
  • Tests

    • New unit and integration tests validating Starknet config handling and /supported responses
  • Bug Fixes

    • Skips incomplete Starknet entries and logs warnings when required values are missing
  • Refactor

    • Centralized Starknet config construction for cleaner configuration handling

@coderabbitai
Copy link

coderabbitai bot commented Feb 21, 2026

No actionable comments were generated in the recent review. 🎉


📝 Walkthrough

Walkthrough

Adds opt-in Starknet support to the facilitator example: a new helper to build Starknet facilitator configs, refactors setup to use it, adds tests validating /supported and config validation behavior, and updates docs and docker-compose with commented Starknet env examples. Starknet remains opt-in via environment variables.

Changes

Cohort / File(s) Summary
Configuration & Documentation
examples/facilitator-server/docker-compose.yml, examples/facilitator-server/src/index.ts, readme.md
Adds commented Starknet environment examples and explanatory comments for opt-in behavior and per-network overrides. No active runtime changes.
Starknet Config Utilities & Setup
examples/facilitator-server/src/starknet-config.ts, examples/facilitator-server/src/setup.ts
Adds buildStarknetConfigs and exported StarknetConfig type; replaces inline Starknet config construction in createDefaultSigners with a call to the new utility. Preserves existing signer setup and return shape.
Tests (E2E & Validation)
examples/facilitator-server/tests/e2e-ci.ts, examples/facilitator-server/tests/starknet-supported.test.ts, examples/facilitator-server/tests/starknet-config-validation.test.ts
Adds/extends tests: CI e2e boot with Starknet envs, integration tests asserting /supported includes Starknet kinds/extra/signers, and unit tests for config validation and skip/fail behavior when required fields are missing.

Sequence Diagram(s)

(Skipped — changes are a utility, config handling, documentation, and tests; control flow is not sufficiently complex to require a sequence diagram.)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I hopped through envs and docs at night,

built configs tidy, kept the startup light,
tests now check paymaster and sponsor true,
opt‑in by vars — ready when you are too,
a rabbit's twitch: small change, big delight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main objective: integrating Starknet support into the facilitator-server with comprehensive test coverage and validation.
Linked Issues check ✅ Passed All linked issue requirements are met: Starknet /supported tests [#41], config validation tests [#41], CI e2e coverage [#41], and documentation [#41] are implemented.
Out of Scope Changes check ✅ Passed All changes are within scope: example-scoped Starknet integration, tests, docs, and CI—no core protocol changes or broad refactoring.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
examples/facilitator-server/tests/starknet-supported.test.ts (1)

31-42: fetchSupported() is called independently in each of the 4 tests — consider beforeAll to avoid redundant setup.

Each it() creates a new facilitator, app, and handles an HTTP request, which means 4× redundant instantiation for a single read-only shared state.

♻️ Proposed refactor
-async function fetchSupported(): Promise<SupportedResponse> {
-  const facilitator = createFacilitator({
-    starknetConfigs: [MAINNET_CONFIG, SEPOLIA_CONFIG],
-  });
-
-  const app = createApp({ facilitator });
-  const response = await app.handle(new Request("http://localhost/supported"));
-
-  expect(response.status).toBe(200);
-
-  return response.json() as Promise<SupportedResponse>;
-}
-
 describe("/supported Starknet integration", () => {
+  let supported: SupportedResponse;
+
+  beforeAll(async () => {
+    const facilitator = createFacilitator({
+      starknetConfigs: [MAINNET_CONFIG, SEPOLIA_CONFIG],
+    });
+    const app = createApp({ facilitator });
+    const response = await app.handle(new Request("http://localhost/supported"));
+    expect(response.status).toBe(200);
+    supported = await response.json() as SupportedResponse;
+  });
+
   it("returns Starknet kinds when Starknet configs are registered", async () => {
-    const supported = await fetchSupported();
     // ...
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/facilitator-server/tests/starknet-supported.test.ts` around lines 31
- 42, The tests call fetchSupported() separately in each it(), causing redundant
creation of facilitator and app; move the setup and single HTTP fetch into a
beforeAll block: create the facilitator via createFacilitator({ starknetConfigs:
[...] }), create the app via createApp({ facilitator }), call app.handle(new
Request("/supported")) once, assert response.status === 200, and store the
parsed SupportedResponse for all tests to reuse instead of invoking
fetchSupported() per test; keep the fetchSupported helper only if you refactor
it to be used by beforeAll or inline the same logic in beforeAll.
examples/facilitator-server/src/starknet-config.ts (1)

4-8: Duplicate StarknetConfig type alias — export from here and remove from setup.ts.

The same conditional-type alias is independently defined in setup.ts (lines 45–49). Since buildStarknetConfigs already lives here, exporting the type avoids drift.

♻️ Proposed refactor
-type StarknetConfig = FacilitatorConfig["starknetConfigs"] extends
+export type StarknetConfig = FacilitatorConfig["starknetConfigs"] extends
   | (infer T)[]
   | undefined
   ? T
   : never;

Then in examples/facilitator-server/src/setup.ts, replace the duplicate declaration with an import:

-import { buildStarknetConfigs } from "./starknet-config.js";
+import { buildStarknetConfigs, type StarknetConfig } from "./starknet-config.js";

-type StarknetConfig = FacilitatorConfig["starknetConfigs"] extends
-  | (infer T)[]
-  | undefined
-  ? T
-  : never;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/facilitator-server/src/starknet-config.ts` around lines 4 - 8, The
StarknetConfig conditional type alias is duplicated; export the existing
StarknetConfig from this file (where buildStarknetConfigs is defined) and remove
the duplicate declaration in setup.ts, then update setup.ts to import the
exported StarknetConfig instead of redefining it; reference the StarknetConfig
type alias and the buildStarknetConfigs symbol to locate the canonical
declaration to export and the duplicate to delete.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@examples/facilitator-server/src/setup.ts`:
- Around line 45-49: The type alias StarknetConfig in setup.ts duplicates the
existing definition in starknet-config.ts; remove this duplicate declaration and
instead import and use the original StarknetConfig type from starknet-config.ts
(replace the local alias in setup.ts with an import and update any references to
use the imported StarknetConfig and FacilitatorConfig as needed).

---

Nitpick comments:
In `@examples/facilitator-server/src/starknet-config.ts`:
- Around line 4-8: The StarknetConfig conditional type alias is duplicated;
export the existing StarknetConfig from this file (where buildStarknetConfigs is
defined) and remove the duplicate declaration in setup.ts, then update setup.ts
to import the exported StarknetConfig instead of redefining it; reference the
StarknetConfig type alias and the buildStarknetConfigs symbol to locate the
canonical declaration to export and the duplicate to delete.

In `@examples/facilitator-server/tests/starknet-supported.test.ts`:
- Around line 31-42: The tests call fetchSupported() separately in each it(),
causing redundant creation of facilitator and app; move the setup and single
HTTP fetch into a beforeAll block: create the facilitator via
createFacilitator({ starknetConfigs: [...] }), create the app via createApp({
facilitator }), call app.handle(new Request("/supported")) once, assert
response.status === 200, and store the parsed SupportedResponse for all tests to
reuse instead of invoking fetchSupported() per test; keep the fetchSupported
helper only if you refactor it to be used by beforeAll or inline the same logic
in beforeAll.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
examples/facilitator-server/tests/starknet-supported.test.ts (1)

56-71: Add explicit toBeDefined() guards before optional-chained .extra assertions

If either find() returns undefined, expect(undefined).toEqual({...}) fails with a confusing mismatch message instead of clearly indicating which kind was not found.

🧪 Proposed improvement for diagnostic clarity
+    expect(mainnetKind).toBeDefined();
+    expect(sepoliaKind).toBeDefined();
+
-    expect(mainnetKind?.extra).toEqual({
+    expect(mainnetKind!.extra).toEqual({
       paymasterEndpoint: MAINNET_CONFIG.paymasterEndpoint,
       sponsorAddress: MAINNET_CONFIG.sponsorAddress,
     });
-    expect(sepoliaKind?.extra).toEqual({
+    expect(sepoliaKind!.extra).toEqual({
       paymasterEndpoint: SEPOLIA_CONFIG.paymasterEndpoint,
       sponsorAddress: SEPOLIA_CONFIG.sponsorAddress,
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/facilitator-server/tests/starknet-supported.test.ts` around lines 56
- 71, Add explicit existence checks before asserting .extra: after computing
mainnetKind and sepoliaKind (from supported.kinds.find(...)), add
expect(mainnetKind).toBeDefined() and expect(sepoliaKind).toBeDefined() so
failures clearly indicate a missing kind before you access optional-chained
.extra in the subsequent toEqual assertions that compare against MAINNET_CONFIG
and SEPOLIA_CONFIG paymasterEndpoint/sponsorAddress.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@examples/facilitator-server/tests/starknet-supported.test.ts`:
- Around line 56-71: Add explicit existence checks before asserting .extra:
after computing mainnetKind and sepoliaKind (from supported.kinds.find(...)),
add expect(mainnetKind).toBeDefined() and expect(sepoliaKind).toBeDefined() so
failures clearly indicate a missing kind before you access optional-chained
.extra in the subsequent toEqual assertions that compare against MAINNET_CONFIG
and SEPOLIA_CONFIG paymasterEndpoint/sponsorAddress.

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.

Incorporate Starknet into examples/facilitator-server with TDD coverage

1 participant