Repository navigation
[PLAN] Prepare GoodWallet for GoodWidget integration #56
Description
[DRAFT][PLAN] Prepare GoodWallet for GoodWidget integration
Closes / tracks: #55
Overview
This plan covers the steps needed to wire @goodwidget/ai-credits-widget into GoodWallet so that authenticated users can open AI Credits from the home dashboard / More drawer. The work is split into two phases:
- Wallet foundation – reusable host infrastructure that any future widget can use (already partially present from Add secure GoodWidget integration boundary #54; gaps to close listed below).
- AI Credits widget integration – the specific registry entry, route, icon, dashboard action, and tests for
@goodwidget/ai-credits-widget.
Phase 1 – Wallet foundation (reusable, widget-agnostic)
These steps produce or harden the hosting surface that every widget, including AI Credits, will rely on.
1.1 Package install & local tarball workflow
Behaviour required
@goodwidget/ai-credits-widgetmust be resolvable at build time.- Because the package is not yet published to npm, the install must use a local tarball produced by
pnpm --filter @goodwidget/ai-credits-widget packinside theGoodDollar/GoodWidgetmonorepo.
Steps
- Document the tarball build +
yarn add file:…workflow in a shortCONTRIBUTINGnote or README section so every developer can reproduce it. - Add a
resolutions/overridesentry inpackage.jsonif the tarball path must be pinned for CI. - Validate that
yarn install(or the project's lock-file flow) succeeds with the tarball reference.
Acceptance criteria
yarn buildcompletes without module-not-found errors for@goodwidget/ai-credits-widget.- Local tarball path is not hard-coded in committed source files; only
package.json/yarn.lockreference it.
1.2 RestrictedEip1193Provider policy completeness
Behaviour required
- The provider policy layer introduced in Add secure GoodWidget integration boundary #54 (
src/widgets/provider/policy.ts) must cover all methods and chain IDs that AI Credits needs. WIDGET_PROVIDER_METHODSandWIDGET_EVM_CHAIN_IDSmust be kept as the single source of truth; no widget entry should bypass them.
Steps
- Audit the AI Credits widget API surface (inspect package exports / README inside
GoodDollar/GoodWidget packages/ai-credits-widget) and list the EIP-1193 methods it calls. - If new methods are required (e.g.
eth_getBalance,eth_call), add them toWIDGET_PROVIDER_METHODSinpolicy.tswith a comment explaining which widget requires them. - Verify
WIDGET_EVM_CHAIN_IDSalready includesCELO_CHAIN_ID(it does – confirm no regression).
Acceptance criteria
- Calling any method the widget needs does not throw "unsupported provider methods" from
RestrictedEip1193Provider. - No existing passing test in
RestrictedEip1193Provider.test.tsis broken.
1.3 AuthenticatedWidgetRoute / bottom-sheet host hardening
Behaviour required
- Unauthenticated access to
/{locale}/[widgetRoute]must redirect to login (already done in Add secure GoodWidget integration boundary #54; confirm it also covers the AI Credits route). - The bottom-sheet must close cleanly on logout (the
resetWalletConnectDialogspattern from Add secure GoodWidget integration boundary #54 may need a parallel reset for widget state).
Steps
- Review
AuthenticatedWidgetRoute.tsxand confirm that session-guard logic is applied generically (not tied to specific widget IDs). - If widget state leaks across logout, add an equivalent
resetWidgetState()call insrc/login/context/SessionContext/storage.tsalongside the existingresetWalletConnectDialogs()call.
Acceptance criteria
- Navigating to
/{locale}/ai-creditswhile unauthenticated renders the login screen, not the widget. - Logging out while a widget bottom-sheet is open does not leave stale widget state.
Phase 2 – AI Credits widget: registry entry, route, dashboard action, icon, and tests
These steps are widget-specific and depend on Phase 1 being complete.
2.1 Registry entry in src/widgets/registry.ts
Behaviour required
- A
defineWidget(…)call must be added toWIDGETSfor@goodwidget/ai-credits-widget. - It must pass all validators in
createWidgetRegistry(exact semver, valid slug, no reserved route, ≥1 chain, all methods in allowlist).
Required fields
| Field | Value |
|---|---|
widgetId |
"goodwidget.ai-credits" |
packageName |
"@goodwidget/ai-credits-widget" |
packageVersion |
Exact semver from the tarball (e.g. "0.1.0") |
routeSlug |
"ai-credits" |
displayName |
"AI Credits" |
integrationMode |
"web-component" (Custom Element ai-credits-widget) |
entry.tagName |
"ai-credits-widget" |
entry.load |
Dynamic import("@goodwidget/ai-credits-widget/register") |
providerPolicy.chainIds |
[CELO_CHAIN_ID] |
providerPolicy.requiredMethods |
Determined in step 1.2 above |
Steps
- Add the
defineWidgetentry toregistry.ts. - Remove it from the
process.env.NEXT_PUBLIC_PLAYWRIGHT_TEST_MODEguard so it is active in production builds (the test fixture widget must stay guard-gated).
Acceptance criteria
createWidgetRegistry(WIDGETS)does not throw.getWidgetByRoute("ai-credits")returns the registered widget.widgetDashboardActionsincludes an entry for AI Credits.
2.2 Dashboard icon for AI Credits
Behaviour required
- The AI Credits
RoundButtonon the home dashboard must display a recognisable icon. - Follow the
DashboardIconunion: prefer{ kind: "system"; name: IconName }if a suitable system icon exists, otherwise use{ kind: "local"; render: () => ReactNode }with an inline SVG or imported asset.
Steps
- Check the
uipackage'sIconNameunion for a suitable icon (e.g."Ai","Credits","Spark"). - If none fits, create a minimal SVG asset under
src/widgets/icons/AiCreditsIcon.tsxand wire it as{ kind: "local", render: () => <AiCreditsIcon /> }.
Acceptance criteria
- An icon renders in the dashboard action button without a broken-image placeholder.
- No new third-party icon library is added.
2.3 Home dashboard and More drawer wiring
Behaviour required
widgetDashboardActions(derived automatically fromWIDGETS) must surface the AI Credits button in the home dashboard action row and the More drawer.- No manual edits to
WalletSection.tsxare needed beyond confirming thatwidgetDashboardActionsis already consumed (it is, from the Add secure GoodWidget integration boundary #54 diff).
Steps
- Confirm
WalletSection.tsxspreads bothcoreDashboardActionsandwidgetDashboardActionsinto the rendered action rows. - Verify that the More drawer (if separate from the inline row) also iterates over all actions including widget-sourced ones.
- Add a translation key
home.aiCredits(or similar) and map it todisplayNameif the label must be localised.
Acceptance criteria
- AI Credits button appears in the home dashboard action row when the user is authenticated.
- Tapping / clicking the button opens the bottom-sheet route at
/{locale}/ai-credits.
2.4 [widgetRoute]/page.tsx static params
Behaviour required
generateStaticParamsinsrc/app/[locale]/@home/(home)/(bottomsheet)/[widgetRoute]/page.tsxalready maps overWIDGETS– no change needed once the registry entry is added in 2.1.
Acceptance criteria
- Next.js static generation includes the
ai-creditsparam without additional code changes.
2.5 Unit tests
Behaviour required
- Registry validation tests must cover the new AI Credits entry.
WidgetRenderer/hostPropertiestests must cover the web-component host path forai-credits-widget.
Steps
- In
src/widgets/registry.test.ts, add a test asserting that the liveWIDGETSarray contains an entry withwidgetId === "goodwidget.ai-credits"and thatcreateWidgetRegistry(WIDGETS)does not throw. - In
src/widgets/WidgetRenderer.test.tsx, add a test renderingAuthenticatedWidgetRoutewithwidgetId="goodwidget.ai-credits"and asserting the Custom Element is mounted. - Mock
@goodwidget/ai-credits-widget/registerin vitest config (add to existing alias map invitest.config.tsor a__mocks__file).
Acceptance criteria
vitest runpasses with zero new failures.- Coverage for the new registry entry is not below the repo's existing threshold.
2.6 Playwright / E2E smoke test
Behaviour required
- A single happy-path smoke test verifying that an authenticated user can open the AI Credits bottom-sheet.
Steps
- Add a test file in
tests-playwright/(follow the naming convention of existing widget/route tests). - Use the
testFixtureWidgetpattern as a reference but target the realai-credits-widgetCustom Element. - Assert that
ai-credits-widgetis present in the DOM and the bottom-sheet is visible.
Acceptance criteria
playwright testfor the new file passes in CI withNEXT_PUBLIC_PLAYWRIGHT_TEST_MODEoff (real widget, not fixture).
Human-reviewer checklist
- Package tarball resolves at build time; no hard-coded local paths in source
-
RestrictedEip1193Providerpolicy covers all methods AI Credits requires - Registry entry passes all validators (exact semver, valid slug, no reserved route)
-
widgetIdfollows thegoodwidget.<slug>convention - Dashboard icon renders; no broken placeholder
- AI Credits button appears in home dashboard for authenticated users
- Unauthenticated access to
/ai-creditsredirects to login - Logout clears any open widget state
- Vitest passes; no regressions in existing widget tests
- Playwright smoke test passes in CI
- No new third-party packages added beyond
@goodwidget/ai-credits-widget - No backwards-compatibility shims introduced
Metadata
Metadata
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity
[-][DRAFT][PLAN] Prepare GoodWallet for GoodWidget integration[/-][+][PLAN] Prepare GoodWallet for GoodWidget integration[/+]L03TJ3 commentedon Oct 23, 2026
Released to wallet and deployed, closing.
follow-ups are separately tracked