Skip to content

feat: multi-buyer identity support in AI Credits widget - #136

Open
blueogin with Copilot wants to merge 5 commits into
mainfrom
copilot/multi-buyer-support-ai-credits-widget-again
Open

feat: multi-buyer identity support in AI Credits widget#136
blueogin with Copilot wants to merge 5 commits into
mainfrom
copilot/multi-buyer-support-ai-credits-widget-again

Conversation

Copilot AI commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

A payer wallet was limited to a single deterministic buyer identity. This adds full multi-buyer identity management: create additional derived buyers, import via private key, register address-only (view/consent) buyers, switch between them, and deep-link assign a partner buyer via URL params.

Runtime contract & session model

  • BuyerRecord type with type: 'derived' | 'imported' | 'address-only', derivationIndex, and label
  • payerSession now stores buyers: BuyerRecord[] + activeBuyerAddress; old single-buyer sessions auto-migrate on first read
  • State gains buyers and activeBuyerAddress; buyerPubKey/buyerPrvKey remain as computed fields from the active buyer

Derivation

  • buildBuyerKeyMessage(address, index) — index 0 preserves the exact legacy message for backward compatibility; index > 0 appends (buyer N)

New adapter actions

Action Behavior
createBuyer Signs wallet message at next derivation index, adds to session
selectBuyer(address) Switches active buyer, resets consent/chain state
importBuyerFromPrivateKey(key) Validates 0x…64hex, derives address, registers as imported
selectBuyerByAddress(address) Registers address-only buyer; sign-required actions disabled
applyDeepLinkBuyer(address, sig) Validates ?buyerAddress=&buyerSignature= URL params on mount, registers partner buyer

UI

  • BuyerOperatorCard: buyer selector list (visible when >1 buyer), "New Buyer" button, collapsible "Import Key" / "Watch Address" panel; address-only buyers show a "view only" badge and Sign Consent is disabled
  • HistoryTab: BuyerFilterSelect dropdown fed via new knownBuyers prop; defaults to active buyer on history tab open
  • useAiCreditsHistory: buyerAddressFilter state + setBuyerAddressFilter action; client-side filtering on entry.buyerAddress

Stories & tests

Three new QA fixtures (MultiBuyerManage, AddressOnlyBuyer, MultiBuyerHistory) and four Playwright smoke tests covering the new flows.

Copilot AI requested review from Copilot and removed request for Copilot July 30, 2026 19:25
Copilot AI linked an issue Jul 30, 2026 that may be closed by this pull request
24 tasks
Co-authored-by: blueogin <43612769+blueogin@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot July 30, 2026 19:40
Copilot AI changed the title [WIP] Add multi-buyer support in AI Credits widget feat: multi-buyer identity support in AI Credits widget Jul 30, 2026
Copilot AI requested a review from blueogin July 30, 2026 19:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands the AI Credits widget runtime/session model from a single deterministic buyer identity to a multi-buyer identity system per payer wallet, adding UI affordances to create/import/watch buyers, switching active buyer context, and filtering history by buyer.

Changes:

  • Introduces BuyerRecord[] + activeBuyerAddress into runtime state/session (with legacy session migration) and adds new adapter actions for buyer lifecycle (create/select/import/watch/deep-link).
  • Updates Manage + History UI to support buyer selection and buyer-based history filtering.
  • Adds Storybook QA fixtures and Playwright smoke coverage for multi-buyer flows.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/widgets/ai-credits-widget/states.spec.ts Adds Playwright smoke tests + screenshots for multi-buyer UI states.
packages/ai-credits-widget/src/widgetRuntimeContract.ts Extends adapter state/actions for multi-buyer support and re-exports BuyerRecord.
packages/ai-credits-widget/src/useAiCreditsHistory.ts Adds buyer filter state/action and client-side filtering by entry.buyerAddress.
packages/ai-credits-widget/src/payerSession.ts Replaces legacy single-buyer session fields with buyers[] + activeBuyerAddress and migration logic.
packages/ai-credits-widget/src/index.ts Exports the new buyer-related types for consumers.
packages/ai-credits-widget/src/components/manage/BuyerOperatorCard.tsx Adds buyer selector UI and import/watch panel; disables signing for address-only buyers.
packages/ai-credits-widget/src/components/history/HistoryTab.tsx Adds buyer filter dropdown fed by known buyers.
packages/ai-credits-widget/src/buyerKeyDerivation.ts Makes derivation message index-aware while preserving index 0 legacy message.
packages/ai-credits-widget/src/AiCreditsWidget.tsx Wires knownBuyers to History UI and defaults history filter to active buyer.
packages/ai-credits-widget/src/adapter.ts Implements multi-buyer session wiring + new actions (create/select/import/watch/deep-link) and URL param parsing.
examples/storybook/src/stories/helpers/aiCreditsWidgetStories.tsx Adds multi-buyer QA fixture stories.
examples/storybook/src/stories/ai-credits-widget/AiCreditsWidgetQA.stories.tsx Exposes new QA fixtures in Storybook.
Suppressed comments (3)

packages/ai-credits-widget/src/adapter.ts:894

  • Deep-link signature validation currently accepts any non-empty hex string (/^0x[0-9a-fA-F]{2,}$/), so malformed/too-short signatures will be treated as “valid”. At minimum, require a 64- or 65-byte signature (EIP-2098 compact or standard) before accepting URL params.
      if (!/^0x[0-9a-fA-F]{2,}$/.test(trimmedSignature)) {
        setState((prev) =>
          withDerivedStatus(prev, { error: 'Deep-link buyer signature is invalid' }, true),
        )
        return

packages/ai-credits-widget/src/adapter.ts:1457

  • Deep-link parsing runs before a payer wallet is connected. When buyerAddress/buyerSignature are present but address is still null, handleApplyDeepLinkBuyer sets an error (“Connect your wallet…”) on mount. Since the effect re-runs after connect anyway, defer applying deep-link params until address is available to avoid a spurious error flash.
  useEffect(() => {
    if (typeof window === 'undefined') return
    const params = new URLSearchParams(window.location.search)
    const urlBuyerAddress = params.get('buyerAddress')
    const urlBuyerSignature = params.get('buyerSignature')

packages/ai-credits-widget/src/components/history/HistoryTab.tsx:524

  • Options in BuyerFilterSelect have role="option" but don’t indicate selection via aria-selected, which is part of the listbox pattern. This makes it harder for screen readers to announce which buyer filter is currently selected.
              tag="button"
              role="option"
              paddingHorizontal="$3"
              paddingVertical="$2"
              cursor="pointer"

Comment thread packages/ai-credits-widget/src/adapter.ts Outdated
Comment thread packages/ai-credits-widget/src/buyerKeyDerivation.ts
Comment thread packages/ai-credits-widget/src/adapter.ts Outdated
Comment thread packages/ai-credits-widget/src/components/history/HistoryTab.tsx
blueogin added 2 commits July 31, 2026 15:19
…ts widget

- Added support for deep link parameters, including buyer address and operator signature, to facilitate buyer registration via NCDI deep links.
- Introduced validation functions for buyer address and operator signature.
- Enhanced state management to handle operator consent and session updates based on deep link data.
- Updated relevant components and types to accommodate new deep link functionality, ensuring a seamless user experience when applying deep links.
- Introduced new functions for managing deep link parameters, including storage and retrieval from local storage.
- Updated error handling to provide clearer messages when deep link parameters are invalid or missing.
- Improved state management to reflect deep link status and errors in the UI, ensuring a better user experience.
- Added a fallback mechanism for deep link processing, enhancing robustness in various scenarios.
- Removed the previous implementation of handleGenerateBuyerKey, consolidating its functionality into handleCreateBuyer for clarity and to preserve backward compatibility.
- Updated comments to reflect changes in buyer key generation logic, ensuring better understanding of the derivation index handling.
- Enhanced the interface documentation for generateBuyerKey to clarify its behavior regarding existing buyers and derivation indices.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Multi-buyer support in AI Credits widget

3 participants