Context
Parent issue: #120
Today a payer wallet maps to a single deterministic buyer in the AI Credits widget. We need to let users create and manage multiple buyer identities from one payer wallet, while keeping all widget operations scoped to the selected buyer.
Relevant code
-
packages/ai-credits-widget/src/adapter.ts
handleGenerateBuyerKey (around line 528) derives a single buyer private key from a payer wallet signature.
AiCreditsWidgetAdapterState (see widgetRuntimeContract.ts) stores only one buyerPubKey / buyerPrvKey pair at a time.
-
packages/ai-credits-widget/src/buyerKeyDerivation.ts
buildBuyerKeyMessage and deriveBuyerPrivateKeyFromSignature currently produce one deterministic key from a single signature / counter loop.
-
packages/ai-credits-widget/src/payerSession.ts
PayerWalletSession currently stores only one buyerPubKey / buyerPrvKey per payer address.
-
packages/ai-credits-widget/src/widgetRuntimeContract.ts
AiCreditsWidgetAdapterActions exposes a single generateBuyerKey action.
- There is no action for selecting, switching, or importing a buyer.
-
packages/ai-credits-widget/src/components/manage/CreditsManagementCard.tsx
- Management UI shows total credit, withdraw, and close channel scoped to the currently loaded buyer.
-
packages/ai-credits-widget/src/components/manage/UsageLog.tsx
- History currently has no buyer filter; entries contain
buyerAddress.
-
packages/ai-credits-widget/src/backendTypes.ts
GdCreditEntry includes a buyerAddress field, supporting per-buyer filtering on the client.
Requirements
- Create and switch between multiple buyer identities from one connected payer wallet.
- Paste a private key to deterministically derive / import a buyer identity.
- Paste a buyer address (without private key) to treat that address as the active buyer for view-only / consent-pairing flows.
- Recover a known buyer after refresh via deterministic derivation per buyer index/label.
- Scope all Manage actions to the selected buyer: balance, consent, withdraw, and API setup.
- Filter History by buyer.
- Accept a buyer address plus a buyer signature for operator assignment via URL GET parameters, so a partner can pass in a pre-generated buyer identity and authorization in a deep link.
Acceptance Criteria
Plan (added by @copilot)
Required states, flows, and behaviors
- Multi-buyer identity model per payer
- Keep a buyer list scoped by payer wallet address.
- Track
activeBuyer and whether it is:
- deterministic (derived index/label),
- imported private-key buyer,
- address-only buyer (no private key, view/consent pairing only).
- Buyer lifecycle flows
- Create buyer from deterministic derivation by index/label.
- Switch active buyer without disconnecting payer wallet.
- Import buyer from pasted private key with strict format validation.
- Select buyer from pasted address without private key.
- Restore known deterministic buyers after reconnect/refresh.
- Scoped runtime behavior
- All actions (balance, consent, withdraw, close channel, API setup) must read/write only the active buyer context.
- Flows requiring signing must fail gracefully for address-only buyers.
- History behavior
- Add buyer filter in history (
All buyers + specific buyer options).
- Default to active buyer when selected; keep option to view all buyer entries.
- Deep-link behavior
- Parse URL params for buyer address + buyer signature.
- Validate signature payload shape and associate only with selected/active buyer.
- Reject malformed/invalid params with non-blocking user feedback.
Execution plan
- Runtime contract/state expansion
- Update
packages/ai-credits-widget/src/widgetRuntimeContract.ts:
- replace single buyer key fields with structured buyer identities + active buyer reference,
- add actions for create/select/import/address-only selection,
- include URL-assignment application action/state where needed.
- Deterministic derivation enhancements
- Update
packages/ai-credits-widget/src/buyerKeyDerivation.ts:
- make derivation deterministic by buyer index/label,
- keep backward-compatible behavior for index
0 (single-buyer users).
- Session persistence model
- Update
packages/ai-credits-widget/src/payerSession.ts:
- persist per-payer buyer list metadata,
- persist active buyer pointer,
- preserve old single-buyer session shape migration on read.
- Adapter flow updates
- Update
packages/ai-credits-widget/src/adapter.ts:
- wire new actions/state transitions,
- scope existing manage/purchase operations to
activeBuyer,
- add URL GET param parsing/validation for buyer address + signature,
- apply operator assignment to selected buyer only.
- Manage & buy UI updates
- Update buyer management UI for create/switch/import/select-address flows in:
packages/ai-credits-widget/src/components/manage/BuyerOperatorCard.tsx
packages/ai-credits-widget/src/components/buy/BuyerKeyPanel.tsx
- Ensure action enablement/disablement reflects buyer capability (has private key vs address-only).
- History filtering
- Update
packages/ai-credits-widget/src/components/manage/UsageLog.tsx to filter by buyerAddress with All buyers option.
- Reuse
packages/ai-credits-widget/src/backendTypes.ts buyerAddress field as filter key.
- Manage card scoping checks
- Verify
packages/ai-credits-widget/src/components/manage/CreditsManagementCard.tsx reads the selected buyer context and enforces key-required actions only when private key is available.
- QA/stories/tests
- Update/add AI Credits stories in:
examples/storybook/src/stories/ai-credits-widget/AiCreditsWidgetQA.stories.tsx
- helper fixtures under
examples/storybook/src/stories/helpers/ (as needed)
- Update/add Playwright smoke coverage in:
tests/widgets/ai-credits-widget/states.spec.ts
- Add scenarios for: multi-buyer switch, private-key import, address-only selection, history filtering, deep-link assignment.
Acceptance criteria (implementation-ready)
Human-reviewer checklist
Context
Parent issue: #120
Today a payer wallet maps to a single deterministic buyer in the AI Credits widget. We need to let users create and manage multiple buyer identities from one payer wallet, while keeping all widget operations scoped to the selected buyer.
Relevant code
packages/ai-credits-widget/src/adapter.tshandleGenerateBuyerKey(around line 528) derives a single buyer private key from a payer wallet signature.AiCreditsWidgetAdapterState(seewidgetRuntimeContract.ts) stores only onebuyerPubKey/buyerPrvKeypair at a time.packages/ai-credits-widget/src/buyerKeyDerivation.tsbuildBuyerKeyMessageandderiveBuyerPrivateKeyFromSignaturecurrently produce one deterministic key from a single signature / counter loop.packages/ai-credits-widget/src/payerSession.tsPayerWalletSessioncurrently stores only onebuyerPubKey/buyerPrvKeyper payer address.packages/ai-credits-widget/src/widgetRuntimeContract.tsAiCreditsWidgetAdapterActionsexposes a singlegenerateBuyerKeyaction.packages/ai-credits-widget/src/components/manage/CreditsManagementCard.tsxpackages/ai-credits-widget/src/components/manage/UsageLog.tsxbuyerAddress.packages/ai-credits-widget/src/backendTypes.tsGdCreditEntryincludes abuyerAddressfield, supporting per-buyer filtering on the client.Requirements
Acceptance Criteria
Plan (added by @copilot)
Required states, flows, and behaviors
activeBuyerand whether it is:All buyers+ specific buyer options).Execution plan
packages/ai-credits-widget/src/widgetRuntimeContract.ts:packages/ai-credits-widget/src/buyerKeyDerivation.ts:0(single-buyer users).packages/ai-credits-widget/src/payerSession.ts:packages/ai-credits-widget/src/adapter.ts:activeBuyer,packages/ai-credits-widget/src/components/manage/BuyerOperatorCard.tsxpackages/ai-credits-widget/src/components/buy/BuyerKeyPanel.tsxpackages/ai-credits-widget/src/components/manage/UsageLog.tsxto filter bybuyerAddresswithAll buyersoption.packages/ai-credits-widget/src/backendTypes.tsbuyerAddressfield as filter key.packages/ai-credits-widget/src/components/manage/CreditsManagementCard.tsxreads the selected buyer context and enforces key-required actions only when private key is available.examples/storybook/src/stories/ai-credits-widget/AiCreditsWidgetQA.stories.tsxexamples/storybook/src/stories/helpers/(as needed)tests/widgets/ai-credits-widget/states.spec.tsAcceptance criteria (implementation-ready)
All buyersview.Human-reviewer checklist
0users.