Skip to content

Fix wallet connection: resolve proving-asset URLs against the page origin - #14

Merged
acedward merged 1 commit into
mainfrom
codex/00007-shielded-night-connect-invalid-url
Sep 8, 2026
Merged

Fix wallet connection: resolve proving-asset URLs against the page origin#14
acedward merged 1 commit into
mainfrom
codex/00007-shielded-night-connect-invalid-url

Conversation

@acedward

@acedward acedward commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Symptom

On https://shielded-night.pages.dev/ (main @ edac395), selecting Preprod and pressing Connect wallet shows Failed to construct 'URL': Invalid URL right after the wallet approves the connection. Preview and Stagenet fail the same way; Preprod was simply the first network reported.

Root cause

frontend/protocols/v1/src/adapter.ts and frontend/protocols/v2/src/adapter.ts passed the relative path ./contract/v1/shielded-night (resp. v2) to FetchZkConfigProvider. Both pinned SDK versions (@midnight-ntwrk/midnight-js-fetch-zk-config-provider 4.1.1 and 5.0.0-beta.7) validate that argument with a bare new URL(baseURL) — no base argument — which throws the browser TypeError for a relative string before any indexer or proving work starts. The pre-#13 code used window.location.origin + '/contract/compiled/…'; the multi-network refactor (#13, 37f1bc4) introduced the relative path and its release notes record that no browser-extension connect was exercised.

Reproduced on the live site with a stub 4.x connector injected as window.midnight.stubWallet (getConfiguration()networkId: 'preprod'): Activity log Connecting StubWallet to Preprod (midnight-1.x)…Connection failed: Failed to construct 'URL': Invalid URL.

Fix

  • New dependency-free frontend/protocols/shared/asset-url.ts: contractAssetBaseUrl(profile, { origin, base }) resolves contract/<v1|v2>/shielded-night against the page origin and the Vite base (import.meta.env.BASE_URL), never against the current page path; requireAbsoluteUrl(value, label, protocols) validates wallet-supplied endpoints with a labelled error.
  • Both adapters now construct FetchZkConfigProvider with that absolute URL and validate indexerUri (http/https) and indexerWsUri (ws/wss) before indexerPublicDataProvider, which performs the same bare new URL() check — a bad wallet value now reads e.g. The wallet returned an invalid indexer URL (""); expected an absolute http: or https: URL. instead of the opaque TypeError.
  • withCompiledFileAssets(ASSET_PATH) is unchanged (compact-js stores the path as metadata only). Served asset paths, vite.config.ts, contract sources, generated artifacts, frontend/.env and workflows are untouched.
  • One sentence in frontend/README.md.

Tests and gates

  • test/unit/frontend-asset-url.unit.test.ts (15 tests): both profiles; base /, unset, /app, /app/, absolute CDN base; origin-not-page-path; the SDK re-check (new URL(result) + protocol) on http and https origins; documentation that new URL('./contract/v1/shielded-night') throws; non-http origin error; requireAbsoluteUrl accept/reject matrix (real Preprod/Preview/Stagenet endpoints; undefined, null, blank, path-only, ftp:, number, scheme crossover) asserting Error not TypeError, the label and the JSON of the value. Mutation control: reverting the resolution to new URL(path) fails 7 of the 15.
  • Root unit suite: 116 → 131 tests passing. Frontend tsc --noEmit and vite build clean; built adapter chunks call the provider with the resolved URL.
  • CI-equivalent gate from a clean git archive of this commit in node:24.15.0-bookworm (bun 1.4.2): root + frontend bun install --frozen-lockfile, npm ci in both protocol trees, frontend typecheck + build (chunk hashes identical to the host build), root bun run test:unit 9 files / 131 tests — exit 0.

Browser verification (no wallet extension available here)

Served the built frontend/dist read-only from nginx:alpine and connected with the stub connector using the public endpoints (indexer.preprod.midnight.network, indexer.preview.midnight.network, indexer.stagenet.shielded.tools, /api/v4/graphql):

  • Connected to Preprod; loaded sNight. / Connected to Preview; loaded sNight. / Connected to Stagenet; loaded sNight. — token name/symbol read live from each contract through the fixed v1/v2 adapters; footer shows the sNight token ids.
  • The key-material provider the v1 adapter hands to getProvingProvider fetched convertToShielded prover key (5,204,863 B), verifier key (2,119 B) and ZKIR (608 B) from the served origin.
  • Negative cases: blank indexerUri and an https:// indexerWsUri produce the labelled messages above. Console clean; zero Invalid URL.

Real-wallet (Lace) signing was not exercised in this environment. To try it before merging, dispatch Deploy frontend with a non-main branch name on this ref for a Cloudflare preview.

Deployment note

Not a breaking change. Merging to main triggers the automatic production deployment through .github/workflows/deploy.yml once push CI is green.

Both protocol adapters passed a relative path
('./contract/v1/shielded-night', './contract/v2/shielded-night')
to FetchZkConfigProvider. The SDK validates that argument with a bare
`new URL(baseURL)` and no base argument (midnight-js-fetch-zk-config-provider
4.1.1 and 5.0.0-beta.7), so the constructor threw
"Failed to construct 'URL': Invalid URL" before any indexer or proving work
started. On https://shielded-night.pages.dev this made Connect wallet fail on
every network; reproduced on 2026-09-08 with a stub 4.x connector on Preprod.

Add the dependency-free frontend/protocols/shared/asset-url.ts and resolve the
served asset tree from window.location.origin plus import.meta.env.BASE_URL, so
a sub-path or absolute Vite base and a non-root SPA route all keep working.
ASSET_PATH stays as withCompiledFileAssets metadata, which is never fetched.

indexerPublicDataProvider validates its endpoints the same way, so the
wallet-supplied indexerUri and indexerWsUri are now checked with
requireAbsoluteUrl and fail with a message naming the field and the received
value instead of the same opaque TypeError.

Served asset paths, contract sources, generated artifacts and frontend/.env are
unchanged.
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.

1 participant