Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
90b9b35
Initial plan
Copilot Jun 23, 2026
804b486
feat: add @goodwidget/ai-credits-widget package
Copilot Jun 23, 2026
d2ab65f
fix: icon color tokens + test selectors; add Playwright screenshots f…
Copilot Jun 24, 2026
d2c2801
fix: correct adapter per review — real buyer key, backend auth consen…
Copilot Jun 24, 2026
bad7032
test: re-capture Playwright screenshots after adapter corrections
Copilot Jun 24, 2026
9f8ba55
Refine buyer key panel UX interactions
Copilot Jun 24, 2026
55f4897
Update ai-credits widget smoke screenshots
Copilot Jun 24, 2026
3763558
Adjust Buyer Key action layout/colors and refresh widget screenshots
Copilot Jun 24, 2026
8e4e4f7
feat: improve Stepper visual hierarchy — active accent bar, completed…
Copilot Jun 24, 2026
c5c29e6
refactor: enhance BuyerKeyPanel messaging and button layout for clari…
blueogin Jun 24, 2026
0888118
feat: implement operator consent flow with EIP-712 signing and backen…
blueogin Jun 24, 2026
3f1e1f5
fix: update G$ token address and use constant for deposits address in…
blueogin Jun 24, 2026
8827a2c
fix: remove unused isVerified variable and handle goodId verification…
blueogin Jun 24, 2026
b8f1de4
feat: batch Celo payment via Multicall3 — stream (Superfluid CFA) + d…
Copilot Jun 24, 2026
d21f679
feat: refactor Celo payment logic into separate module for improved c…
blueogin Jun 24, 2026
3887a3c
test: refresh ai-credits-widget Playwright screenshots (13/13 pass)
Copilot Jun 24, 2026
7542d76
feat: enhance ai-credits-widget with improved credit handling and usa…
blueogin Jun 24, 2026
b2f3d0d
feat: implement account status loading and operator consent improveme…
blueogin Jun 25, 2026
3e7b9bf
feat: enhance mock backend client with improved account state managem…
blueogin Jun 25, 2026
8d60330
feat: update buyer key generation to derive from wallet signature and…
blueogin Jun 25, 2026
5437f8a
refactor: remove paste buyer key functionality from ai-credits-widget…
blueogin Jun 25, 2026
ae98eba
feat: implement buyer validation and refactor account status loading …
blueogin Jun 25, 2026
29e9e6a
feat: enhance ai-credits-widget with bought credits tracking and impr…
blueogin Jun 25, 2026
e8cd1d9
fix: correct has_credits test assertion + refresh Playwright screensh…
Copilot Jun 25, 2026
371451b
feat: enhance AmountPicker component to display credits alongside USD…
blueogin Jun 26, 2026
f42ce6f
refactor: remove disconnected state rendering from AiCreditsWidget an…
blueogin Jun 26, 2026
5dedbb1
fix: clarify EIP-712 SetOperator message description in OperatorConse…
blueogin Jun 26, 2026
e33e53f
feat: add purchase flow functionality to ai-credits-widget, including…
blueogin Jun 26, 2026
f8c5add
feat: implement clipboard functionality for copying text in ai-credit…
blueogin Jun 26, 2026
d8ee154
test: refresh Playwright screenshots + update lockfile (13/13 pass)
Copilot Jun 26, 2026
85c3211
refactor: update ai-credits-widget to streamline purchase flow and en…
blueogin Jul 2, 2026
65846d8
refactor: rename CreditsAccount to CreditsManagement and update relat…
blueogin Jul 2, 2026
1a74a2e
feat: enhance ai-credits-widget with improved quote handling, additio…
blueogin Jul 2, 2026
28cd525
chore: update test images for ai-credits-widget, including new scenar…
blueogin Jul 2, 2026
be6db18
feat: add InfoTooltip component and enhance AddressView in ai-credits…
blueogin Jul 2, 2026
d9ce4e6
feat: introduce mergeStatePreservingManagement function to streamline…
blueogin Jul 2, 2026
6a456f0
feat: update AiCreditsWidget showcase and enhance state management wi…
blueogin Jul 2, 2026
46a4fff
feat: integrate vault payment minimums into ai-credits-widget, enhanc…
blueogin Jul 2, 2026
ff291be
feat: enhance ai-credits-widget with buyer key management, improved c…
blueogin Jul 2, 2026
c430ba1
fix: update error messages and tooltips in ai-credits-widget for clea…
blueogin Jul 2, 2026
4313794
chore: update test images for ai-credits-widget to reflect new scenar…
blueogin Jul 2, 2026
3821765
feat: add payment validation messaging and tooltip support in ai-cred…
blueogin Jul 2, 2026
0da5705
feat: update AiCreditsWidget documentation and components to include …
blueogin Jul 2, 2026
68eddc1
feat: refactor operator consent handling in ai-credits-widget to impr…
blueogin Jul 3, 2026
92cbc61
feat: enhance AiCreditsWidget documentation and components with new o…
blueogin Jul 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ playwright-report/
local-reference-assets
.vercel
.env*


.agents
skills-lock.json
1 change: 1 addition & 0 deletions examples/storybook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@goodwidget/claim-widget-theme-demo": "workspace:*",
"@goodwidget/citizen-claim-widget": "workspace:*",
"@goodwidget/staking-migration-widget": "workspace:*",
"@goodwidget/ai-credits-widget": "workspace:*",
"react": "^18.3.0",
"react-dom": "^18.3.0",
"react-native-web": "^0.19.13",
Expand Down
106 changes: 106 additions & 0 deletions examples/storybook/src/stories/ai-credits-widget/AiCreditsWidget.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { Canvas, Meta } from '@storybook/blocks';
import * as ShowcaseStories from './AiCreditsWidgetShowcase.stories';
import { DocsCallout, DocsCard, DocsGrid, DocsPage, DocsSection } from '../docs/DocsLayout';

<Meta of={ShowcaseStories} />

<DocsPage
eyebrow="Widget Guide"
title="AiCreditsWidget"
lead="Buy AI coding credits with G$ on Celo. Credits settle on Base and are redeemable with AntSeed-compatible AI coding tools like Cursor and Cline."
>
<DocsSection
title="Interactive showcase (mock backend)"
description="Uses your browser wallet (`window.ethereum`, e.g. Rabby) with the in-memory mock backend — no local antseed worker required."
>
<Canvas of={ShowcaseStories.MockBackend} />
</DocsSection>

<DocsSection
title="Injected wallet"
description="Uses your browser wallet (`window.ethereum`, e.g. Rabby), `VITE_AI_CREDITS_BACKEND_URL`, `VITE_AI_CREDITS_BASE_RPC_URL`, `VITE_AI_CREDITS_FUNDING_VAULT_ADDRESS`, and `VITE_AI_CREDITS_VAULT_ADDRESS` from `examples/storybook/.env.local`."
>
<Canvas of={ShowcaseStories.InjectedWallet} />
</DocsSection>

<DocsSection
title="QA coverage"
description="Use the QA demo when you need reproducible fixture states, Playwright screenshots, or fixture-driven debugging."
>
<DocsCard
title="Open the QA fixture demo"
href="?path=/story/qa-aicreditswidget-runtime-fixtures--disconnected"
>
All 10 widget states as deterministic mock fixtures — ideal for automation and debugging.
</DocsCard>
</DocsSection>

<DocsSection
title="Widget states"
description="The widget uses a flat 10-state status union, consistent with other GoodWidget packages."
>
<DocsGrid>
<DocsCard title="S1 – Disconnected">No wallet connected.</DocsCard>
<DocsCard title="S2 – Purchase Setup">Wallet connected; buyer key / consent / amounts in progress.</DocsCard>
<DocsCard title="S3 – Quote Ready">Setup complete; on-chain quote built; ready to pay.</DocsCard>
<DocsCard title="S4 – Payment Pending">Celo tx submitted.</DocsCard>
<DocsCard title="S5 – Payment Confirmed">Settling on Base.</DocsCard>
<DocsCard title="S6 – Credits Management">AI credits balance &gt; 0; management dashboard with stream, history, and API setup.</DocsCard>
<DocsCard title="S7 – Insufficient G$">G$ below minimum purchase threshold.</DocsCard>
<DocsCard title="S8 – Payment Failed">Transaction or settlement error.</DocsCard>
<DocsCard title="S9 – Backend Unavailable">Backend unreachable.</DocsCard>
<DocsCard title="S10 – Unsupported Chain">Wrong network (Celo required).</DocsCard>
</DocsGrid>
</DocsSection>

<DocsSection
title="Backend API usage"
description="Production stories call the antseed-integration worker for reads, settlement, and management actions."
>
<DocsGrid>
<DocsCard title="GET …/credit">Credits profile and funding history for the payer wallet.</DocsCard>
<DocsCard title="GET …/outstanding">Pending or failed Base funding entries.</DocsCard>
<DocsCard title="POST …/celo/events/record">Notify `{ txHash }` after a successful Celo payment.</DocsCard>
<DocsCard title="POST …/accounts/:buyer/operator-consent">
Buyer-signed SetOperator relay — backend submits `acceptBuyerOperator` on Base (no buyer gas).
</DocsCard>
<DocsCard title="POST …/channels/:channelId/close">Buyer-signed channel close from credits management.</DocsCard>
<DocsCard title="POST …/accounts/:buyer/withdraw">Buyer-signed principal withdraw to the payer wallet.</DocsCard>
</DocsGrid>
<DocsCallout title="On-chain (not backend)" tone="info">
Vault minimum reads, quotes, withdrawable principal, and Celo deposit/stream transactions are
handled on-chain via RPC. Buyer EIP-712 signing for operator consent, close, and withdraw
happens in the widget; only the Base submission is relayed by the worker. There is no
channel-list API — paste the channel ID manually.
</DocsCallout>
</DocsSection>

<DocsSection
title="Known limitations"
description="Features that still need operator care in production."
>
<DocsCallout title="Buyer private key session" tone="warning">
Close channel and withdraw require the buyer private key in the current browser session. Use
Sign &amp; Generate in Buyer &amp; Operator on the credits management screen if the key was
lost after refresh.
</DocsCallout>
<DocsCallout title="Vault minimums" tone="info">
First-deposit USD minimum applies only when `totalDepositedGd(payer)` is zero. Monthly stream
USD minimum applies on every stream create/update.
</DocsCallout>
<DocsCallout title="Base bridge" tone="info">
Operator consent, close, withdraw, and credit funding require the worker&apos;s Base operator
bridge to be configured (`bridge.enabled: true` in API responses).
</DocsCallout>
</DocsSection>

<DocsSection
title="Workflow guidance"
description="Choose the story type based on the job you are trying to do."
>
<DocsCallout title="Rule of use" tone="info">
Use the showcase story when validating the product-facing integration flow. Use the QA fixture
stories when you need state-flow coverage, screenshots, or reproducible runtime conditions.
</DocsCallout>
</DocsSection>
</DocsPage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import type { Meta, StoryObj } from '@storybook/react'
import { AiCreditsWidget } from '@goodwidget/ai-credits-widget'
import {
DisconnectedStory,
PurchaseSetupStory,
QuoteReadyStory,
QuoteReadyGoodIdStory,
PaymentPendingStory,
PaymentConfirmedStory,
CreditsManagementStory,
InsufficientGBalanceStory,
PaymentFailedStory,
BackendUnavailableStory,
UnsupportedChainStory,
} from '../helpers/aiCreditsWidgetStories'

const meta: Meta<typeof AiCreditsWidget> = {
title: 'QA/AiCreditsWidget/Runtime Fixtures',
component: AiCreditsWidget,
tags: ['autodocs', 'qa'],
parameters: { layout: 'padded' },
}

export default meta
type Story = StoryObj<typeof meta>

export const Disconnected: Story = {
render: () => <DisconnectedStory />,
}

export const PurchaseSetup: Story = {
render: () => <PurchaseSetupStory />,
}

export const QuoteReady: Story = {
render: () => <QuoteReadyStory />,
}

export const QuoteReadyGoodId: Story = {
render: () => <QuoteReadyGoodIdStory />,
}

export const PaymentPending: Story = {
render: () => <PaymentPendingStory />,
}

export const PaymentConfirmed: Story = {
render: () => <PaymentConfirmedStory />,
}

export const CreditsManagement: Story = {
render: () => <CreditsManagementStory />,
}

export const InsufficientGBalance: Story = {
render: () => <InsufficientGBalanceStory />,
}

export const PaymentFailed: Story = {
render: () => <PaymentFailedStory />,
}

export const BackendUnavailable: Story = {
render: () => <BackendUnavailableStory />,
}

export const UnsupportedChain: Story = {
render: () => <UnsupportedChainStory />,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { Meta, StoryObj } from '@storybook/react'
import { AiCreditsWidget } from '@goodwidget/ai-credits-widget'
import { InjectedWalletStory, MockBackendStory } from '../helpers/aiCreditsWidgetStories'

const meta: Meta<typeof AiCreditsWidget> = {
title: 'Widgets/AiCreditsWidget/Showcase',
component: AiCreditsWidget,
tags: ['integrator', 'manual', 'showcase'],
parameters: { layout: 'padded' },
}

export default meta
type Story = StoryObj<typeof meta>

export const MockBackend: Story = {
name: 'Mock Backend (browser wallet)',
render: () => <MockBackendStory />,
}

export const InjectedWallet: Story = {
name: 'Injected Wallet',
render: () => <InjectedWalletStory />,
}
Loading