Fix wallet connection: resolve proving-asset URLs against the page origin - #14
Merged
Merged
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Symptom
On https://shielded-night.pages.dev/ (
main@edac395), selecting Preprod and pressing Connect wallet showsFailed to construct 'URL': Invalid URLright 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.tsandfrontend/protocols/v2/src/adapter.tspassed the relative path./contract/v1/shielded-night(resp.v2) toFetchZkConfigProvider. Both pinned SDK versions (@midnight-ntwrk/midnight-js-fetch-zk-config-provider4.1.1 and 5.0.0-beta.7) validate that argument with a barenew URL(baseURL)— no base argument — which throws the browserTypeErrorfor a relative string before any indexer or proving work starts. The pre-#13 code usedwindow.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 logConnecting StubWallet to Preprod (midnight-1.x)…→Connection failed: Failed to construct 'URL': Invalid URL.Fix
frontend/protocols/shared/asset-url.ts:contractAssetBaseUrl(profile, { origin, base })resolvescontract/<v1|v2>/shielded-nightagainst 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.FetchZkConfigProviderwith that absolute URL and validateindexerUri(http/https) andindexerWsUri(ws/wss) beforeindexerPublicDataProvider, which performs the same barenew 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/.envand workflows are untouched.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 thatnew URL('./contract/v1/shielded-night')throws; non-http origin error;requireAbsoluteUrlaccept/reject matrix (real Preprod/Preview/Stagenet endpoints;undefined,null, blank, path-only,ftp:, number, scheme crossover) assertingErrornotTypeError, the label and the JSON of the value. Mutation control: reverting the resolution tonew URL(path)fails 7 of the 15.tsc --noEmitandvite buildclean; built adapter chunks call the provider with the resolved URL.git archiveof this commit innode:24.15.0-bookworm(bun 1.4.2): root + frontendbun install --frozen-lockfile,npm ciin both protocol trees, frontend typecheck + build (chunk hashes identical to the host build), rootbun run test:unit9 files / 131 tests — exit 0.Browser verification (no wallet extension available here)
Served the built
frontend/distread-only fromnginx:alpineand 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.getProvingProviderfetchedconvertToShieldedprover key (5,204,863 B), verifier key (2,119 B) and ZKIR (608 B) from the served origin.indexerUriand anhttps://indexerWsUriproduce the labelled messages above. Console clean; zeroInvalid URL.Real-wallet (Lace) signing was not exercised in this environment. To try it before merging, dispatch Deploy frontend with a non-
mainbranch name on this ref for a Cloudflare preview.Deployment note
Not a breaking change. Merging to
maintriggers the automatic production deployment through.github/workflows/deploy.ymlonce push CI is green.