AI Credits Widget: buy developer AI credits with G$
This sub-issue defines the execution plan for the UI-only implementation of the AI Credits Widget described in parent issue #30.
The parent issue remains unchanged and is the product source of truth.
Parent issue: #30
Required states, flows, and behaviors
Required states
disconnected
connected_empty
quote_ready
payment_pending
payment_confirmed
has_credits
usage_empty
usage_active
insufficient_g_balance
insufficient_ai_credits
payment_failed
backend_unavailable
unsupported_chain
Required flows
- Connect wallet
- Show wallet address and G$ balance
- Choose purchase mode:
- one-time purchase
- streaming/top-up mode
- Enter G$ amount
- Show quote:
- G$ amount
- estimated AI credit value
- highlighted top-up/bonus
- monthly value if streaming mode is selected
- plain-English note that backend handles Antseed settlement underneath
- Submit buy action
- Show pending confirmation state
- On success, show:
- AI credit balance
- masked API key
- copyable setup instructions
- Show usage log after billed requests exist
- Support retry/degraded/unsupported states without implying payment success
Required UI behaviors
- Linear compact card flow only; no marketplace/provider/team billing UI
- API key masked by default with show/hide and copy
- Copyable setup blocks for OpenAI-compatible tools
- Usage rows must include model, status, estimated/captured cost, timestamp
- Billing copy must consistently use hold/capture/release semantics
- Main UX must not expose USDC/channel complexity
- Integration must remain fixture/mock-backed until a real backend URL/config is provided
Relevant reference files
GoodWidget implementation references
packages/claim-widget/ — closest package and publishable widget reference
packages/ui/ — shared primitives, tokens, alerts, cards, buttons, input-like controls
packages/core/ — GoodWidgetProvider, wallet/runtime boundaries, EIP-1193 integration
packages/embed/ — embeddable export pattern if needed
examples/storybook/fixtures/custodialEip1193.ts
examples/storybook/fixtures/injectedEip1193.ts
antseed-integration architecture and API references
GoodDollar/antseed-integration/AGENTS.md
GoodDollar/antseed-integration/README.md
GoodDollar/antseed-integration/docs/ARCHITECTURE.md
GoodDollar/antseed-integration/docs/PAYMENT_FLOW.md
GoodDollar/antseed-integration/backend/README.md
GoodDollar/antseed-integration/backend/src/types.ts
GoodDollar/antseed-integration/backend/src/pricing.ts
GoodDollar/antseed-integration/contracts/src/AgentCreditVault.sol
GoodDollar/antseed-integration/contracts/src/CeloGdAntSeedVault.sol
Relevant code references from GoodDollar/antseed-integration
Architecture / boundary references
AGENTS.md
- Confirms this repo is the backend + smart-contract integration layer and that UI work belongs in
GoodDollar/GoodWidget
- Source of truth for UI agents: auth/API key endpoints, credit quote/account balance endpoints, Celo deposit/stream ingestion flows, and OpenAI-compatible
/v1/chat/completions
- States that billing language should use hold/reserve before request, capture/settle after successful billable response, and release on failure/non-billable response
docs/PAYMENT_FLOW.md
- Defines the two-layer model:
- GoodDollar user/credit layer
- AntSeed buyer payment layer
- Confirms the widget must not imply native G$ settlement to sellers
- Confirms the backend owns request reserve/release/settle lifecycle and forwards requests to the AntSeed buyer gateway
docs/ARCHITECTURE.md
- Defines accounting model:
available = deposited - reserved
reserve(requestId, account, amount)
settle(requestId, actualCost)
release(requestId)
- Confirms backend is Cloudflare Worker owned and frontend is out of scope for that repo
Backend API references for mocked UI contract
backend/README.md
- Endpoints relevant to UI mocking and future integration:
POST /v1/auth/nonce
POST /v1/auth/api-keys
GET /v1/auth/api-keys
DELETE /v1/auth/api-keys/:id
GET /v1/accounts/:account/credit
GET /v1/requests/:requestId
POST /v1/credits/quote
POST /v1/chat/completions
- Confirms production auth shape uses
gd_live_... keys
- Confirms credit rules:
- non-streaming deposits receive 110% credits
- active streamers receive 120% credits up to monthly stream-speed cap
Domain model references for UI state design
backend/src/types.ts
CreditReservation
- useful for payment pending / confirmed / released / failed UI states
- includes
status, maxCostMicroUsd, actualCostMicroUsd, timestamps, and receipt/vault hashes
UserCreditProfile
- useful for wallet balance, total credits, reserved credits, deposited amount, streaming-derived values
GdCreditEntry
- useful for displaying source/type of issued credit and bonus breakdown
AntSeedChatCompletion
- useful for usage/result fixture shape
backend/src/pricing.ts
estimateMaxCostMicroUsd(...)
actualCostMicroUsd(...)
- useful reference for quote fixtures and for separating estimated reserve from captured final cost in UI copy
Contract references for UX wording and state modeling
contracts/src/AgentCreditVault.sol
availableBalance(address) supports the “available vs reserved” mental model
reserve(...) maps to pre-request hold/authorization language
settle(...) maps to post-success capture language
release(...) maps to refund/release-on-failure language
- event names are useful as semantic references for state naming:
CreditReserved
CreditSettled
CreditReleased
contracts/src/CeloGdAntSeedVault.sol
- shows supported G$ deposit sources:
- ERC20 deposit
- ERC677/ERC667 callback deposits
- ERC777 callback deposits
- Superfluid stream callbacks
- confirms GoodID verification boundary
- exposes stream state concepts that should inform streaming purchase mode copy:
streamFlowRate
streamMonthlyGdAmount
StreamUpdated
- reinforces that backend converts G$ events into USDC-denominated credits under the hood, not the widget
Execution plan
1. Package and structure planning
- Create a new package under
packages/ai-credits-widget/
- Follow
packages/claim-widget structure for:
- entrypoints
- provider wiring
- embeddable widget surface
- story organization
- package publishing shape
- Add Playwright smoke coverage under
tests/widgets/ai-credits-widget/
2. Dependency and shared package mapping
- Import existing
@goodwidget / GoodDollar shared packages instead of creating custom infrastructure:
packages/ui
packages/core
packages/embed
- Reuse theme tokens, card/layout primitives, buttons, copyable controls, badges, alerts, and wallet-aware provider boundaries where available
3. New component mapping
Create widget-local components first, then evaluate promotion into packages/ui only if they are clearly generic and reusable.
Proposed widget-local components:
AiCreditsWidgetShell
AiCreditsHeaderCard
AiCreditsProgressStepper
AiCreditsPurchaseModeToggle
AiCreditsPurchaseForm
AiCreditsQuoteCard
AiCreditsPaymentStatusCard
AiCreditsApiKeyCard
AiCreditsSetupSnippetCard
AiCreditsBalanceCard
AiCreditsUsageCard
AiCreditsUsageTable
AiCreditsEmptyUsageState
AiCreditsErrorStateCard
AiCreditsUnsupportedChainCard
Candidates to promote to packages/ui only if existing equivalents do not exist:
- generic compact progress stepper
- generic masked secret display with show/hide/copy
- generic copyable config/snippet block
- generic usage/status table row pattern
4. Fixture and integration planning
- Keep all backend interactions fixture-driven
- Define adapter/interface boundaries for:
- wallet connect state
- quote fetch
- payment submission
- payment status polling
- API key retrieval
- usage retrieval
- Mock contract/backend-driven values using reference semantics from:
backend/src/types.ts
backend/src/pricing.ts
docs/PAYMENT_FLOW.md
5. Storybook planning
Create stories for:
- Disconnected initial state
- Connected with zero credits
- Quote ready
- Payment pending
- Payment confirmed with API key/setup visible
- Has credits with empty usage
- Has credits with recent usage rows
- Insufficient G$ balance
- Payment failed
- Backend unavailable
- Unsupported chain
Use wallet fixtures where relevant:
examples/storybook/fixtures/custodialEip1193.ts
examples/storybook/fixtures/injectedEip1193.ts
6. Playwright planning
- Add smoke tests for the main states under
tests/widgets/ai-credits-widget/
- Capture screenshot evidence for:
- disconnected
- connected empty
- quote ready
- pending
- confirmed
- has credits
- payment failed
- backend unavailable
- unsupported chain
7. UX/copy review planning
- Ensure all copy reflects backend-first hosted OpenAI-compatible API MVP
- Setup snippets must prioritize:
OPENAI_BASE_URL=https://<backend-domain>/v1
OPENAI_API_KEY=<developer_platform_key>
- Any local proxy copy must be marked optional / coming later unless a real wrapper exists
- Ensure copy consistently says:
- user pays with G$
- backend handles AntSeed settlement underneath
Acceptance criteria
- A draft implementation plan exists for the new
packages/ai-credits-widget/ package
- The plan maps all required widget states, flows, and behaviors from the parent issue
- The plan references
GoodDollar/antseed-integration architecture, API, pricing, and contract files as integration/source-of-truth inputs
- The plan identifies which components belong in the widget package vs possible reusable
packages/ui promotion candidates
- The plan specifies Storybook scenarios and Playwright smoke coverage
- The plan preserves the MVP boundary:
- UI only
- fixture-backed integrations
- no direct AntSeed settlement implementation
- no subscriptions/org billing/marketplace scope creep
human-reviewer checklist
AI Credits Widget: buy developer AI credits with G$
This sub-issue defines the execution plan for the UI-only implementation of the AI Credits Widget described in parent issue #30.
The parent issue remains unchanged and is the product source of truth.
Parent issue: #30
Required states, flows, and behaviors
Required states
disconnectedconnected_emptyquote_readypayment_pendingpayment_confirmedhas_creditsusage_emptyusage_activeinsufficient_g_balanceinsufficient_ai_creditspayment_failedbackend_unavailableunsupported_chainRequired flows
Required UI behaviors
Relevant reference files
GoodWidget implementation references
packages/claim-widget/— closest package and publishable widget referencepackages/ui/— shared primitives, tokens, alerts, cards, buttons, input-like controlspackages/core/—GoodWidgetProvider, wallet/runtime boundaries, EIP-1193 integrationpackages/embed/— embeddable export pattern if neededexamples/storybook/fixtures/custodialEip1193.tsexamples/storybook/fixtures/injectedEip1193.tsantseed-integration architecture and API references
GoodDollar/antseed-integration/AGENTS.mdGoodDollar/antseed-integration/README.mdGoodDollar/antseed-integration/docs/ARCHITECTURE.mdGoodDollar/antseed-integration/docs/PAYMENT_FLOW.mdGoodDollar/antseed-integration/backend/README.mdGoodDollar/antseed-integration/backend/src/types.tsGoodDollar/antseed-integration/backend/src/pricing.tsGoodDollar/antseed-integration/contracts/src/AgentCreditVault.solGoodDollar/antseed-integration/contracts/src/CeloGdAntSeedVault.solRelevant code references from GoodDollar/antseed-integration
Architecture / boundary references
AGENTS.mdGoodDollar/GoodWidget/v1/chat/completionsdocs/PAYMENT_FLOW.mddocs/ARCHITECTURE.mdavailable = deposited - reservedreserve(requestId, account, amount)settle(requestId, actualCost)release(requestId)Backend API references for mocked UI contract
backend/README.mdPOST /v1/auth/noncePOST /v1/auth/api-keysGET /v1/auth/api-keysDELETE /v1/auth/api-keys/:idGET /v1/accounts/:account/creditGET /v1/requests/:requestIdPOST /v1/credits/quotePOST /v1/chat/completionsgd_live_...keysDomain model references for UI state design
backend/src/types.tsCreditReservationstatus,maxCostMicroUsd,actualCostMicroUsd, timestamps, and receipt/vault hashesUserCreditProfileGdCreditEntryAntSeedChatCompletionbackend/src/pricing.tsestimateMaxCostMicroUsd(...)actualCostMicroUsd(...)Contract references for UX wording and state modeling
contracts/src/AgentCreditVault.solavailableBalance(address)supports the “available vs reserved” mental modelreserve(...)maps to pre-request hold/authorization languagesettle(...)maps to post-success capture languagerelease(...)maps to refund/release-on-failure languageCreditReservedCreditSettledCreditReleasedcontracts/src/CeloGdAntSeedVault.solstreamFlowRatestreamMonthlyGdAmountStreamUpdatedExecution plan
1. Package and structure planning
packages/ai-credits-widget/packages/claim-widgetstructure for:tests/widgets/ai-credits-widget/2. Dependency and shared package mapping
@goodwidget/ GoodDollar shared packages instead of creating custom infrastructure:packages/uipackages/corepackages/embed3. New component mapping
Create widget-local components first, then evaluate promotion into
packages/uionly if they are clearly generic and reusable.Proposed widget-local components:
AiCreditsWidgetShellAiCreditsHeaderCardAiCreditsProgressStepperAiCreditsPurchaseModeToggleAiCreditsPurchaseFormAiCreditsQuoteCardAiCreditsPaymentStatusCardAiCreditsApiKeyCardAiCreditsSetupSnippetCardAiCreditsBalanceCardAiCreditsUsageCardAiCreditsUsageTableAiCreditsEmptyUsageStateAiCreditsErrorStateCardAiCreditsUnsupportedChainCardCandidates to promote to
packages/uionly if existing equivalents do not exist:4. Fixture and integration planning
backend/src/types.tsbackend/src/pricing.tsdocs/PAYMENT_FLOW.md5. Storybook planning
Create stories for:
Use wallet fixtures where relevant:
examples/storybook/fixtures/custodialEip1193.tsexamples/storybook/fixtures/injectedEip1193.ts6. Playwright planning
tests/widgets/ai-credits-widget/7. UX/copy review planning
OPENAI_BASE_URL=https://<backend-domain>/v1OPENAI_API_KEY=<developer_platform_key>Acceptance criteria
packages/ai-credits-widget/packageGoodDollar/antseed-integrationarchitecture, API, pricing, and contract files as integration/source-of-truth inputspackages/uipromotion candidateshuman-reviewer checklist
[DRAFT][PLAN] ...[DRAFT] ...TaskGoodDollar/antseed-integrationfiles are explicitly mappedparent:
repository: "GoodDollar/GoodWidget"
number: 30
url: "AI Credits Widget: buy developer AI credits with G$ #30"