You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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-widget must 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 pack inside the GoodDollar/GoodWidget monorepo.
Steps
Document the tarball build + yarn add file:… workflow in a short CONTRIBUTING note or README section so every developer can reproduce it.
Add a resolutions / overrides entry in package.json if 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 build completes 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.lock reference it.
WIDGET_PROVIDER_METHODS and WIDGET_EVM_CHAIN_IDS must 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 to WIDGET_PROVIDER_METHODS in policy.tswith a comment explaining which widget requires them.
Verify WIDGET_EVM_CHAIN_IDS already includes CELO_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.ts is broken.
Review AuthenticatedWidgetRoute.tsx and 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 in src/login/context/SessionContext/storage.ts alongside the existing resetWalletConnectDialogs() call.
Acceptance criteria
Navigating to /{locale}/ai-credits while 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 to WIDGETS for @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)
Remove it from the process.env.NEXT_PUBLIC_PLAYWRIGHT_TEST_MODE guard 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.
widgetDashboardActions includes an entry for AI Credits.
2.2 Dashboard icon for AI Credits
Behaviour required
The AI Credits RoundButton on the home dashboard must display a recognisable icon.
Follow the DashboardIcon union: 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 ui package's IconName union for a suitable icon (e.g. "Ai", "Credits", "Spark").
If none fits, create a minimal SVG asset under src/widgets/icons/AiCreditsIcon.tsx and 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 from WIDGETS) must surface the AI Credits button in the home dashboard action row and the More drawer.
No manual edits to WalletSection.tsx are needed beyond confirming that widgetDashboardActions is already consumed (it is, from the Add secure GoodWidget integration boundary #54 diff).
Steps
Confirm WalletSection.tsx spreads both coreDashboardActions and widgetDashboardActions into 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 to displayName if 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
generateStaticParams in src/app/[locale]/@home/(home)/(bottomsheet)/[widgetRoute]/page.tsx already maps over WIDGETS – no change needed once the registry entry is added in 2.1.
Acceptance criteria
Next.js static generation includes the ai-credits param without additional code changes.
2.5 Unit tests
Behaviour required
Registry validation tests must cover the new AI Credits entry.
WidgetRenderer / hostProperties tests must cover the web-component host path for ai-credits-widget.
Steps
In src/widgets/registry.test.ts, add a test asserting that the live WIDGETS array contains an entry with widgetId === "goodwidget.ai-credits" and that createWidgetRegistry(WIDGETS) does not throw.
In src/widgets/WidgetRenderer.test.tsx, add a test rendering AuthenticatedWidgetRoute with widgetId="goodwidget.ai-credits" and asserting the Custom Element is mounted.
Mock @goodwidget/ai-credits-widget/register in vitest config (add to existing alias map in vitest.config.ts or a __mocks__ file).
Acceptance criteria
vitest run passes 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 testFixtureWidget pattern as a reference but target the real ai-credits-widget Custom Element.
Assert that ai-credits-widget is present in the DOM and the bottom-sheet is visible.
Acceptance criteria
playwright test for the new file passes in CI with NEXT_PUBLIC_PLAYWRIGHT_TEST_MODE off (real widget, not fixture).
Human-reviewer checklist
Package tarball resolves at build time; no hard-coded local paths in source
RestrictedEip1193Provider policy covers all methods AI Credits requires
Registry entry passes all validators (exact semver, valid slug, no reserved route)
widgetId follows the goodwidget.<slug> convention
Dashboard icon renders; no broken placeholder
AI Credits button appears in home dashboard for authenticated users
Unauthenticated access to /ai-credits redirects 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
[DRAFT][PLAN] Prepare GoodWallet for GoodWidget integration
Closes / tracks: #55
Overview
This plan covers the steps needed to wire
@goodwidget/ai-credits-widgetinto GoodWallet so that authenticated users can open AI Credits from the home dashboard / More drawer. The work is split into two phases:@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.pnpm --filter @goodwidget/ai-credits-widget packinside theGoodDollar/GoodWidgetmonorepo.Steps
yarn add file:…workflow in a shortCONTRIBUTINGnote or README section so every developer can reproduce it.resolutions/overridesentry inpackage.jsonif the tarball path must be pinned for CI.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.package.json/yarn.lockreference it.1.2
RestrictedEip1193Providerpolicy completenessBehaviour required
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
GoodDollar/GoodWidget packages/ai-credits-widget) and list the EIP-1193 methods it calls.eth_getBalance,eth_call), add them toWIDGET_PROVIDER_METHODSinpolicy.tswith a comment explaining which widget requires them.WIDGET_EVM_CHAIN_IDSalready includesCELO_CHAIN_ID(it does – confirm no regression).Acceptance criteria
RestrictedEip1193Provider.RestrictedEip1193Provider.test.tsis broken.1.3
AuthenticatedWidgetRoute/ bottom-sheet host hardeningBehaviour required
/{locale}/[widgetRoute]must redirect to login (already done in Add secure GoodWidget integration boundary #54; confirm it also covers the AI Credits route).resetWalletConnectDialogspattern from Add secure GoodWidget integration boundary #54 may need a parallel reset for widget state).Steps
AuthenticatedWidgetRoute.tsxand confirm that session-guard logic is applied generically (not tied to specific widget IDs).resetWidgetState()call insrc/login/context/SessionContext/storage.tsalongside the existingresetWalletConnectDialogs()call.Acceptance criteria
/{locale}/ai-creditswhile unauthenticated renders the login screen, not the widget.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.tsBehaviour required
defineWidget(…)call must be added toWIDGETSfor@goodwidget/ai-credits-widget.createWidgetRegistry(exact semver, valid slug, no reserved route, ≥1 chain, all methods in allowlist).Required fields
widgetId"goodwidget.ai-credits"packageName"@goodwidget/ai-credits-widget"packageVersion"0.1.0")routeSlug"ai-credits"displayName"AI Credits"integrationMode"web-component"(Custom Elementai-credits-widget)entry.tagName"ai-credits-widget"entry.loadimport("@goodwidget/ai-credits-widget/register")providerPolicy.chainIds[CELO_CHAIN_ID]providerPolicy.requiredMethodsSteps
defineWidgetentry toregistry.ts.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
RoundButtonon the home dashboard must display a recognisable icon.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
uipackage'sIconNameunion for a suitable icon (e.g."Ai","Credits","Spark").src/widgets/icons/AiCreditsIcon.tsxand wire it as{ kind: "local", render: () => <AiCreditsIcon /> }.Acceptance criteria
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.WalletSection.tsxare needed beyond confirming thatwidgetDashboardActionsis already consumed (it is, from the Add secure GoodWidget integration boundary #54 diff).Steps
WalletSection.tsxspreads bothcoreDashboardActionsandwidgetDashboardActionsinto the rendered action rows.home.aiCredits(or similar) and map it todisplayNameif the label must be localised.Acceptance criteria
/{locale}/ai-credits.2.4
[widgetRoute]/page.tsxstatic paramsBehaviour 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
ai-creditsparam without additional code changes.2.5 Unit tests
Behaviour required
WidgetRenderer/hostPropertiestests must cover the web-component host path forai-credits-widget.Steps
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.src/widgets/WidgetRenderer.test.tsx, add a test renderingAuthenticatedWidgetRoutewithwidgetId="goodwidget.ai-credits"and asserting the Custom Element is mounted.@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.2.6 Playwright / E2E smoke test
Behaviour required
Steps
tests-playwright/(follow the naming convention of existing widget/route tests).testFixtureWidgetpattern as a reference but target the realai-credits-widgetCustom Element.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
RestrictedEip1193Providerpolicy covers all methods AI Credits requireswidgetIdfollows thegoodwidget.<slug>convention/ai-creditsredirects to login@goodwidget/ai-credits-widget