Skip to content

Align web payments with Hub and preserve wallet and network context - #976

Merged
dangershony merged 6 commits into
mainfrom
web-payment-polish
Oct 14, 2026
Merged

dangershony merged 6 commits into
mainfrom
web-payment-polish

Conversation

@Zazawowow

@Zazawowow Zazawowow commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Web payments now retain the Hub's network, active indexer and theme, and provide one consistent Invest, Fund and Subscribe flow. Completed payments use a compact, vertically centered card with transaction and recovery actions instead of a full-width green banner.

Changes:

  • Match Hub navigation, surfaces, responsive payment layouts and funding-pattern cards; preserve fixed subscription amounts and require a valid offered plan.
  • Offer the desktop app for payments of 0.01 BTC or more before creating a browser wallet.
  • Preserve existing wallets on mismatched network links and prevent background health checks from overwriting newly selected connection settings.
  • Use asynchronous browser BIP-39 derivation, reuse the signing-key cache and yield between address derivations. Copy controls show inline success/retry feedback.
  • Keep initial connecting relays eligible for project discovery while excluding failed connections.

This branch is based on current main and contains only the web-payment work and its shared dependencies. Companion Hub change: block-core/angor-hub#43

Validation:

  • Debug build and Release publish passed with .NET 8.0.310.
  • Full Angor.Shared.Tests suite: 166 passed, zero failed or skipped. Full Angor.Sdk.Tests suite: 349 passed, 14 existing skips, zero failures.
  • Published-build completion, payment-dialog/threshold/keyboard-focus/backup and plan checks passed in Chromium 153, Firefox 155 and WebKit 26.6 on Linux, at desktop 1440├ù900 and phone 390├ù844. Both themes, all payment types, reload, transaction links, deletion guard, plan handoff, fixed prices and responsive widths were exercised.
  • A real Angornet Fund payment passed invoice funding, investment broadcast, independent indexer verification, reload persistence and access to the original recovery phrase. Investment transaction: b57b2d9424c75760794286b71f0f3841db865185a5550bb666e518b225bf8a8c.
  • Live Hub ÔåÆ testnet invoice, address-copy feedback, BIP-39 compatibility and preserving an existing wallet on a mismatched network link passed.

Remaining validation limits:

  • Live Lightning payment needs configured test payer credentials. Live Invest completion needs founder approval; neither is claimed as end-to-end verified. Subscribe is covered by UI and shared protocol tests, not a live payment.
  • Desktop recovery/import and real-device Safari were not exercised. Linux WebKit with phone viewport is not an iPhone test.
  • Existing compiler warnings and the existing HtmlSanitizer 8.0.843 NU1902 advisory remain. No mainnet funds, deployment or merge were involved.
  • Isolated Chromium Release wallet preparation passed the unchanged 1.5-second event-loop target: largest measured pause 1.18 seconds. An earlier run under concurrent browser/build load measured 1.65 seconds; this is a local measurement, not a guarantee for every device.

Browser scenarios, wallet state, recovery phrases and traces are kept outside the repository and are not uploaded.

Founder pages are investor-only

Browser wallets created on the invest page have no founder keys. Create, Founder and Spend show an investor-only notice ("This browser wallet is investor-only. Import your recovery phrase into the Angor app to create or manage projects.") instead of throwing.

Manual recovery test script (to be run by a human; results not filled in yet)

  1. On Angornet, open /invest/{projectId}?network=Angornet in a clean browser profile.
  2. Let it auto-create a wallet. Copy the recovery phrase.
  3. Fund the wallet and invest the minimum amount. Record the txid: ____
  4. In the desktop app (src/design), import the phrase on Angornet.
  5. Confirm the remaining balance matches and the investment shows in Portfolio with the same txid.
  6. Run Recover or Penalties on it in desktop and confirm the keys sign correctly.

Result: ____ (not yet performed)

…handoff tests

Remove window.deriveWalletSeed, WalletKeyService and GetOrDeriveExtKeyAsync; derivation is lazy via GetOrDeriveExtKey again. Founder/Create/Spend show an investor-only message when the browser wallet has no founder keys. Extract network/amount handoff rules into InvestHandoff. Add BIP-39 cross-derivation tests and Angor.Client.Tests. Restore index.html icon links.
dangershony added a commit that referenced this pull request Oct 14, 2026
…Error

Drop IndexerFailoverHandler and its registration, restore original HttpClient keys/timeouts, use #976's NostrCommunicationFactory, revert out-of-scope global.json/AGENTS.md/dev-run.sh/.gitignore. Add tests: 5xx/403/408/429 mark indexer offline, 404 does not.
@dangershony
dangershony marked this pull request as ready for review October 14, 2026 22:36
@dangershony
dangershony merged commit 52cf260 into main Oct 14, 2026
3 checks passed
@dangershony
dangershony deleted the web-payment-polish branch October 14, 2026 22:37
dangershony added a commit that referenced this pull request Oct 14, 2026
* chore(dev): support Linux development after macOS migration

* docs: UX/UI audit report for next version

* feat(ux): toast severity fix, keyboard access, semantic tokens, typography migration, password reveal, seed UX

- Fix: failure toasts (claim/release/wallet create/import/settings/funders/edit-profile)
  no longer render as green success toasts — ToastRequested now carries ToastSeverity
  end-to-end; all failure call sites pass ToastSeverity.Error
- Keyboard: global :focus-visible ring (V2 theme replaced Fluent templates so none existed);
  Escape closes shell modals / steps back (reuses TryHandlePlatformBack) at shell root,
  plus Settings network/wipe modals; accessible names on icon-only shell buttons
- Tokens: danger/warning/Bitcoin accent literal hexes migrated to semantic brushes
  (DangerBrush, DangerBrightBrush, DangerSoftBrush, WarningBrush, WarningBrightBrush,
  WarningSoftBrush, BitcoinAccentBrush)
- Typography: 938 TextBlock FontSize attributes migrated to Typography classes
  (Size-XXS..XXL + interim exact-pixel Size-10..80 gap steps); XMl validated pre-write
- Tooltips: truncated bound TextBlocks now show the full value on hover (31 sites)
- Passwords: eye reveal toggles on PrivateKeysPasswordModal + claim/release password
  fields; plaintext-download warning + live seed word-count hint in CreateWalletModal
- Dead code: remove InvestPageViewModel.SubmitOpacity (real CanSubmit/IsEnabled is used)

* fix(theme): use FocusAdornerTemplate for :focus-visible ring (ControlTemplate is invalid)

* docs: handoff notes for further-ux-polish branch

* feat(find-projects): virtualize project grid + hex-literal regression guard

- Project grid now row-chunks (ProjectRowViewModel) and renders via
  VirtualizingStackPanel + UniformRowPanel: only visible rows materialize and
  recycle instead of inflating every ProjectCard in a non-virtualizing
  ResponsiveGrid. View reports width-driven column count to the VM which
  re-chunks rows synchronously (keeps headless tests deterministic).
- ProjectListVirtualizationTests: chunk order/count invariants + rendered
  proof that long lists only realize viewport rows (+overscan).
- HexLiteralGuardTests: first source-scan test — fails if the seven migrated
  danger/warning/Bitcoin hexes reappear as literals in UI/{Sections,Shell,Shared}.
- ResponsiveGrid unchanged for the bounded grids (MyProjects, Portfolio).

* chore: keep UX polish notes local

* Recover from server outages and improve project loading UX

* fix(theme): use semantic danger brush for claim scan errors

* fix(invest): reject insufficient wallet funds before relay lookups

* Remove indexer failover; restore indexer clients; test CheckAndHandleError

Drop IndexerFailoverHandler and its registration, restore original HttpClient keys/timeouts, use #976's NostrCommunicationFactory, revert out-of-scope global.json/AGENTS.md/dev-run.sh/.gitignore. Add tests: 5xx/403/408/429 mark indexer offline, 404 does not.

* Propagate indexer failures and harden SDK callers

MempoolIndexerAngorApi keeps EnsureSuccessStatusCode and lets HTTP/JSON/timeout errors propagate. SpendStageFunds, CancelInvestmentRequest, CreateProjectKeys and GetPenalties return Result.Failure instead of throwing. Tests: 5xx and HTML 200 never yield an empty success.

* Skip failing projects in Nostr discovery; test insufficient-funds check

BEHAVIOUR CHANGE: LatestFromNostrAsync no longer fails all-or-nothing; one project whose validation fails is skipped and the rest are returned. ProjectDiscoveryRecoveryTests reworked accordingly. Retry with ConcurrentDictionary kept. Add InvestWithWallet funds-check tests.

* RequestInvestmentSignatures: fail closed when the indexer is unreachable

Check the existing-investment lookup before any seed-word access or Nostr send; an indexer failure now returns a Result.Failure. Add tests (throws, existing, null). Document why CheckExistingInvestment intentionally fails open.

---------

Co-authored-by: dangershony <dan.gershony@gmail.com>
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.

2 participants