Skip to content

Next into Master - #352

Merged
pietro909 merged 144 commits into
masterfrom
next
Mar 12, 2026
Merged

pietro909 merged 144 commits into
masterfrom
next

Conversation

@pietro909

@pietro909 pietro909 commented Mar 2, 2026 •

Copy link
Copy Markdown
Contributor

Used to get an up-to-date version of next.

Summary by CodeRabbit

  • New Features

    • Delegates settings screen with toggle, connectivity checks, default delegate helper, and settings entry.
    • UI: new dark-purple shadow variant, scalable arrow icon, and dashed horizontal rule utility.
  • Bug Fixes

    • Improved swap subscription cleanup to avoid leaks/races.
    • Fixed QR receive event payload handling and payload validation.
  • Chores

    • Updated Boltz Swap and SDK to new pre-release versions; added package manager config.
    • Migration and storage updates: backup/restore, service worker, and wallet flows now use IndexedDB-backed repositories and migration support.
  • Tests

    • Added unit and end-to-end tests for Delegates flow.

@coderabbitai

coderabbitai Bot commented Mar 2, 2026 •

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Replace direct IndexedDB contract persistence with injected SwapRepository/localStorage, migrate worker/lightning/wallet to a MessageBus + service-worker model, add Delegates settings UI and tests, refactor async swap subscription cleanup, and bump boltz-swap/sdk deps with pnpm config.

Changes

Cohort / File(s) Summary
Dependency & Manifest
package.json
Bump @arkade-os/boltz-swap and @arkade-os/sdk to pre-release versions; add pnpm config (ignoredBuiltDependencies, onlyBuiltDependencies).
Service worker & MessageBus
src/wallet-service-worker.ts, src/providers/lightning.tsx, src/providers/wallet.tsx
Switch worker runtime to MessageBus; wire IndexedDB repositories into message handlers; replace ArkadeLightning initialization with ServiceWorkerArkadeLightning.create; add lifecycle (create/dispose) and status/migration ping logic.
Swap persistence & Backup/Restore
src/lib/backup.ts, src/screens/Init/Restore.tsx, src/screens/Settings/Backup.tsx, src/providers/config.tsx
Inject SwapRepository into BackupProvider; callers now pass IndexedDbSwapRepository(); restore/save now use swapRepository.saveSwap instead of prior contractRepo persistence.
Indexer & Batch lifetime
src/lib/indexer.ts, src/lib/wallet.ts
Persist commitment timestamps to localStorage, rename getCommitmentTxCreatedAt → getAndUpdateCommitmentTxCreatedAt, add get/set helpers; calcBatchLifetimeMs now accepts an Indexer instance.
Async swap subscriptions
src/components/SwapsList.tsx, src/screens/Apps/Boltz/Swap.tsx
Refactor swap update subscriptions to support promise-based subscribe/unsubscribe with cancellation guards and guarded cleanup to avoid state updates after unmount.
Wallet migration & storage
src/providers/wallet.tsx, src/wallet-service-worker.ts
Add migration flow using IndexedDBWalletRepository/IndexedDBContractRepository, migrateWalletRepository, getMigrationStatus, rollbackMigration; pass repositories into ServiceWorkerWallet.setup and use clear() for resets.
Delegates feature (UI + tests)
src/screens/Settings/Delegates.tsx, src/providers/options.tsx, src/screens/Settings/Index.tsx, src/test/...
Add Delegates settings screen, option entry and index wiring, connection testing, toggle UI, unit and e2e tests, and update mocks to include delegate flag.
Types & Config
src/lib/types.ts, src/lib/constants.ts, src/providers/config.tsx
Add delegate: boolean to Config, new Delegate type and defaultDelegate() helper; default config sets delegate = true.
Small UI/UX & events
src/components/Shadow.tsx, src/components/Toggle.tsx, src/icons/Arrow.tsx, src/index.css, src/ionic.css, src/screens/Wallet/Onboard.tsx, src/screens/Wallet/Receive/QrCode.tsx
Add darkPurple to Shadow, reorder ToggleProps.text, add Arrow small prop, new .dashed-hr CSS class, adjust ion-toggle handle size, change event.payload paths for VTXO/UTXO updates with shape guards.
Utilities & formatting
src/lib/format.ts, src/lib/constants.ts
Guard prettyAgo for falsy timestamps and add environment-aware defaultDelegate() URL resolution.

Sequence Diagram(s)

sequenceDiagram
  participant UI as Client/UI
  participant SW as ServiceWorker (MessageBus)
  participant Wallet as ServiceWorkerWallet
  participant SwapRepo as IndexedDbSwapRepository
  participant Lightning as ServiceWorkerArkadeLightning

  Note over UI,SW: Initialization
  UI->>SW: start/create MessageBus
  SW->>Wallet: setup(storage: {walletRepository, contractRepository})
  SW->>SwapRepo: instantiate IndexedDbSwapRepository
  SW->>Lightning: ServiceWorkerArkadeLightning.create(swapRepository, arkServerUrl)
  Lightning-->>SW: ready
  Wallet-->>SW: wallet ready
  SW-->>UI: started

  Note over UI,SwapRepo: Backup / Restore
  UI->>SW: trigger fullBackup()/restore()
  SW->>SwapRepo: read/write swaps via swapRepository.saveSwap(...)
  SwapRepo-->>SW: ack
  SW-->>UI: operation complete

  Note over Lightning,SwapRepo: Runtime swap persistence
  Lightning->>SwapRepo: swapRepository.saveSwap(swap)
  SwapRepo-->>Lightning: ack
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • bordalix
  • Kukks
🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Next into Master' is vague and generic, failing to convey meaningful information about the changeset's purpose or scope. Consider a more descriptive title that captures the main objective, such as 'Upgrade SDK dependencies and add delegate support' or 'Merge next branch: SDK upgrades and delegate configuration'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch next

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

bordalix and others added 28 commits March 11, 2026 09:42
* fix(ui): match iOS/Android status bar color to app theme

The status bar stayed white in dark mode because:
- The theme-color meta tag was hardcoded to #000000
- Safari doesn't reliably support media queries on theme-color
- The html element had no background-color, so the safe area defaulted to white

Fix: inline script in <head> reads the stored theme from localStorage
and sets theme-color + ion-palette-dark class before first paint.
applyTheme() keeps it in sync on manual toggle. Root element background
now follows --ion-background-color so the safe area fills correctly.

* fix(ui): add dev-only logging to theme bootstrap catch block

Address CodeRabbit nitpick: log theme init failures on localhost
so broken localStorage/config parsing is visible during development.

* fix(ios): status bar color matching and content overlap for iOS 26+ PWA

iOS 26+ ignores the theme-color meta tag — it derives the status bar
color from the actual rendered content at the top of the page. Add a
position:fixed body::before pseudo-element that sits behind the
transparent status bar and uses var(--ion-background-color), so iOS
samples the correct theme color instantly on theme switch.

Push .ion-page below the safe area with top: env(safe-area-inset-top)
using ion-app > .ion-page selector (higher specificity than Ionic's
core .ion-page { top: 0 } which loads later in the cascade).

Also fix manifest.json theme_color (#fff) and improve inline theme
bootstrap comments in index.html.

* style: fix prettier formatting in ionic.css

* fix(ui): match theme enum casing in bootstrap script

The Themes enum uses capitalized values ('Dark', 'Light', 'Auto') but
the inline bootstrap script compared against lowercase. This caused
the dark-mode flash prevention to fail when theme was explicitly set.

Also makes the iOS status bar comment version-agnostic per review.

---------

Co-authored-by: Sahil Chaturvedi <sahilc0@users.noreply.github.com>
* fix max balance when sending btc with assets

* fix keyboard when sending assets
fix(pwa): fix swipe-back navigation for iOS standalone mode
* style(assets): rebrand Assets to Arkade Mint with pixel coin icon

- Rename "Assets" to "Arkade Mint" across all asset screens (list, settings, mint success)
- Replace placeholder "A" icon with Mario-style pixel coin in Arkade purple
- New icon matches size/format of other app icons (55px/78px)

* style(apps): redesign app cards with subtle surface treatment

Replace Shadow border+borderPurple cards with whisper-surface style:
- Subtle background tint instead of gray bg + harsh purple border
- Tactile press state with scale(0.97) + background darken
- Touch events matching Button component pattern (mouse + touch)
- Icon aligned to top-left, description nested under title
- Inline accessibility (role, tabIndex, keyboard handler)

src/screens/Apps/Index.tsx

* style: fix prettier formatting

* fix(test): update test selectors after Assets → Arkade Mint rename

The app card testId changed from 'app-assets' to 'app-arkade-mint' and
the header/settings text changed accordingly.

* fix(test): update 'Back to Assets' → 'Back to Arkade Mint' in tests

MintSuccess button text was renamed but tests still referenced old text.

---------

Co-authored-by: Sahil Chaturvedi <sahilc0@users.noreply.github.com>
Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
Co-authored-by: Pietro Grandi <dev@pietro.uno>
* Upgrade ts-sdk@0.4.3 and boltz-swap@0.3.2

* Update SW
…stall banner (#375)

* feat(onboarding): remove onboarding carousel, skip straight to wallet

Remove the 4-step onboarding carousel (Onboard.tsx) and all supporting
components (StepBars, Bullet, AlertBox, Announcement, Onboard1-4 SVGs).
New users now go directly from Init → InitConnect → Wallet instead of
through the carousel. The announcement/PSA system is also removed as it
interrupted the flow without providing value.

Files removed:
- src/screens/Wallet/Onboard.tsx (carousel screen)
- src/components/AlertBox.tsx, Announcement.tsx, Bullet.tsx, StepBars.tsx
- src/icons/Onboard1-4.tsx (~10,800 lines of SVG illustrations)
- src/providers/announcements.tsx (PSA announcement system)
- Associated tests for removed components

Files modified:
- src/App.tsx: route to Init instead of Onboard for new wallets
- src/screens/Init/*.tsx: navigate to InitConnect instead of InitSuccess
- src/providers/navigation.tsx: remove Onboard from Pages enum
- src/index.tsx: remove AnnouncementProvider wrapper
- src/test/e2e/utils.ts: remove onboard steps from createWallet helper

* feat(wallet): add dismissible PWA install banner and password nudge

Add a new DismissibleBanner component used for both the PWA install
prompt and the password creation nudge. The banner features Framer Motion
enter/exit animations (EASE_OUT_QUINT, y:-24, scale:0.97), horizontal
swipe-to-dismiss gesture, layout animation for smooth sibling reflow,
and prefers-reduced-motion support with 44px touch targets.

PWA install banner:
- Mobile-only gating (isIOS || isAndroid) — hidden on desktop
- Platform-specific descriptions (iOS share sheet vs Android install)
- Module-level beforeinstallprompt capture for native install prompt
- Respects persistent dismissed state via config.dismissedBanners

Password nudge:
- Replaced old AlertBox with DismissibleBanner (expanded layout)
- Added nudgeVisible/nudgeCheckComplete to context for PWA banner
  priority coordination (PWA banner waits for nudge check)
- Fixed error handling: .catch/.finally on async password check

Config: replaced announcementsSeen with dismissedBanners (existing
configs handled gracefully via ?? [] fallbacks).

New files:
- src/components/DismissibleBanner.tsx

Modified:
- src/screens/Wallet/Index.tsx (PWA banner integration)
- src/providers/nudge.tsx (DismissibleBanner + error handling)
- src/lib/pwa.ts (usePwaInstalled, beforeinstallprompt, promptPwaInstall)
- src/lib/types.ts, src/providers/config.tsx (dismissedBanners)
- src/ionic.css (--purple10 color variable)
- src/test/setup.ts (matchMedia mock)

* fix: address CodeRabbit review feedback

- Password.tsx: reset restoring flag when navigating to InitConnect
  to prevent stale state from a previous restore attempt
- DismissibleBanner.tsx: disable layout animation and popLayout mode
  when prefers-reduced-motion is active
- Wallet/Index.tsx: only show Install action button when native
  prompt is available (Android); iOS shows instruction-only banner

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(wallet): clarify iOS PWA banner instruction text

Update the iOS PWA install banner description to reference "the share
icon in Safari's toolbar" instead of generic "the share button" so
users know exactly where to look.

* fix(pwa): return prompt outcome and auto-dismiss banner after install

promptPwaInstall() now returns 'accepted' | 'dismissed' | null instead
of void. On Android, the banner auto-dismisses after the user interacts
with the native install prompt, rather than staying visible.

* fix(banner): add haptic feedback to DismissibleBanner interactions

Fire hapticSubtle() on button taps (Dismiss, Install, Set password)
and on swipe-to-dismiss gesture, consistent with all other interactive
elements in the app.

* feat(onboarding): add animated SVG logo morph sequence with delight effects

Redesign the Init screen with a rich onboarding animation:

- OnboardingLogo: SVG cross-fade between Arcade, Space Invader, and Heart
  shapes with deep squash-stretch bounces using Framer Motion async
  animation controls. Final bounce flies logo to header position via FLIP.
- PixelSplash: burst of purple pixel particles on each bounce
- PixelSunrise: pixelated purple gradient at screen top (fixed position)
- Three bullet points with outlined icon components (Bolt, Globe, ShieldCheck)
  replacing the old paragraph text
- Reduced motion: all animations skip, content renders instantly

Files: OnboardingLogo.tsx, PixelSplash.tsx, PixelSunrise.tsx,
BoltOutline.tsx, GlobeOutline.tsx, ShieldCheckOutline.tsx,
Init.tsx, ionic.css

* style(onboarding): fix Prettier formatting in OnboardingLogo and Init

* style(onboarding): smooth radial gradient, layout + status bar fixes

- PixelSunrise: replace pixelated grid with smooth radial-gradient,
  remove all pixel dissolution code
- Init: move content to bottom of screen (flex-end + paddingBottom),
  stack logo above title with optical alignment to bullet icons
- Status bar: add apple-mobile-web-app-capable for PWA bleed-through,
  set theme-color to #8771BC (computed gradient top on white),
  fix manifest.json theme_color mismatch
- Dynamic theme-color useEffect on Init screen for Safari tinting

* style(onboarding): fix Prettier formatting in Init

* fix(onboarding): stable fly target, gradient portal, dark mode prep

- Always render content in DOM (hidden until ready) so logoTargetRef
  position is stable during fly animation instead of shifting on mount
- Portal OnboardingLogo and PixelSunrise to document.body so they
  escape IonPage's max-width: 640px container on desktop
- Add color-scheme light/dark to :root and .ion-palette-dark
- Add color-scheme meta tag and body background-color for Safari
- Sunrise animation synced with fly via onFlyStart callback
- Snappier bounce physics: deeper squash, higher overshoot, faster timings

* style(onboarding): fix Prettier formatting in Init.tsx

* feat(onboarding): pixel morph animation, spring physics, loading bypass

Logo morph animation:
- Rewrite OnboardingLogo to use pixel-shapes.ts grid system instead of
  opacity crossfade between SVG path components
- Arcade "A" always renders as clean SVG paths (never pixelated), while
  Invader and Heart shapes use pixel rects with CSS transform transitions
- Spring-based bounce recovery (stiffness: 600, damping: 18, mass: 0.6)
  replaces scripted multi-step keyframes for natural overshoot feel
- Morph + bounce happen simultaneously — shape swap at squash peak
- Faster timing: 180ms initial pause, 60ms between morphs, ~1s total
- Portal to document.body so logo escapes IonPage max-width on desktop

Pixel splash particles:
- Increase from 12-17 to 20-28 particles per burst
- Wider velocity range (25-105) and more size variation (2.5-6.5px)

Skip loading screen for new users:
- New users (no wallet in storage) bypass ASP + JS capability gates,
  going straight to Init where the logo morph serves as intro visual
- Wallet provider reads from localStorage synchronously via lazy
  useState initializer, eliminating one-frame Loading flash
- "Create wallet" button stays disabled until ASP resolves

Revert status bar changes:
- All theme-color, color-scheme, and apple-mobile-web-app changes from
  this branch reverted — will be handled in a separate PR
- Remove temp replay button and associated state

Files: OnboardingLogo.tsx, PixelSplash.tsx, Init.tsx, App.tsx,
       wallet.tsx, index.html, manifest.json, ionic.css, index.css

* fix(wallet): remove unused setWalletLoaded setter

walletLoaded is now always true (synchronous init), so the setter is
dead code. Replace useState with a constant to satisfy eslint.

* Apply suggestion from @tiero

Signed-off-by: Marco Argentieri <3596602+tiero@users.noreply.github.com>

* fix: use named export for PageTransition to fix Rollup tree-shaking

Rollup's module concatenation was dropping the default export definition
while keeping the JSX references, causing 'PageTransition is not defined'
at runtime. Named exports are handled more reliably.

* fix: update e2e helpers for new onboarding flow (no more InitSuccess page)

The onboarding flow now goes Init → InitConnect → Wallet directly,
skipping the InitSuccess page. The createWallet() and restoreWallet()
helpers were waiting for "Your new wallet is live!" / clicking
"Go to wallet" which no longer exist, causing all Playwright tests
to hang indefinitely.

---------

Signed-off-by: Marco Argentieri <3596602+tiero@users.noreply.github.com>
Co-authored-by: Sahil Chaturvedi <sahilc0@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Marco Argentieri <3596602+tiero@users.noreply.github.com>
Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
…virtual (#394)

* test: add smoke test for TransactionsList with large tx history

Reproduces the reported lag on wallets with several thousand transactions.
TransactionsList renders every row into the DOM at once with no windowing;
render time scales linearly (~1.8ms/tx in jsdom), so:
  100 txs  →   471ms  ✓
  500 txs  → 1,475ms  ✗
 1000 txs  → 2,258ms  ✗
 3000 txs  → 5,477ms  ✗
 5000 txs  → 9,206ms  ✗

The fix is to virtualise the list (e.g. @tanstack/react-virtual).
This test will serve as the regression gate once that is in place.

https://claude.ai/code/session_01LDxnFdhREuPcK3yPCkQUMU

* perf(transactions): virtualise TransactionsList with @tanstack/react-virtual

Fixes the wallet freeze / extreme lag reported for wallets with several
thousand transactions.

Root cause
----------
TransactionsList rendered every Tx into the DOM unconditionally via a plain
.map() call.  With no windowing, render time scaled linearly with the
transaction count (~1.8 ms/tx in jsdom, worse in a real browser due to
layout and paint):

  Before fix (all DOM nodes mounted):
    100 txs  →    471 ms
    500 txs  →  1 475 ms
   1000 txs  →  2 258 ms
   3000 txs  →  5 477 ms
   5000 txs  →  9 206 ms

Fix
---
Replace the plain map() with @tanstack/react-virtual's useVirtualizer.
Only the rows that fit in the viewport (+ a 5-row overscan buffer above
and below) are ever mounted in the DOM.  The total DOM node count is now
O(visible rows) ≈ 15–25 regardless of wallet history size.

  After fix (virtual rows only):
    100 txs  →  4 ms ✓
    500 txs  →  3 ms ✓
   1000 txs  →  4 ms ✓
   3000 txs  →  4 ms ✓
   5000 txs  →  3 ms ✓

The list renders in a self-contained scrollable container
(height: calc(100dvh - 380px), min-height: 200px) so the balance/buttons
section above it remains static — a common pattern in mobile wallet UIs.

Smoke test update
-----------------
- Added a DOM-count assertion: at most MAX_DOM_ROWS (20) rows may be
  mounted at any one time, ensuring virtualisation cannot regress silently.
- Retained the per-count render-time assertions (≤ 500 ms) as a belt-and-
  braces guard.

https://claude.ai/code/session_01LDxnFdhREuPcK3yPCkQUMU

* feat(TransactionsList): add ArrowUp/ArrowDown keyboard navigation with virtualizer scroll-sync

Add focusedIndex state and handleListKeyDown on the parentRef scroll
container. Arrow key presses call virtualizer.scrollToIndex(next) then
requestAnimationFrame to focus the target Focusable row once it is
mounted. Existing Enter → handleClick and Escape → focusOnOuterShell
behaviour is preserved; Tab is unchanged.

https://claude.ai/code/session_01LDxnFdhREuPcK3yPCkQUMU

* fix(TransactionsList): guard focusRow and focusOnFirstRow against empty/out-of-range indices

Add an early-return bounds check in focusRow (index < 0 || index >= txs.length)
to prevent virtualizer.scrollToIndex and key(txs[index]) from executing on
invalid indices. Move the txs.length === 0 guard before setFocused(true) in
focusOnFirstRow so focused is never set true when there are no rows to navigate.
The focusRow guard also covers the edge case in handleListKeyDown where
txs.length === 0 would produce a -1 next index.

https://claude.ai/code/session_01LDxnFdhREuPcK3yPCkQUMU

* remove transactions smoke test

https://claude.ai/code/session_01LDxnFdhREuPcK3yPCkQUMU

* fix(keyboard): sync focusedIndex with actual DOM focus on row focus events (#397)

* Initial plan

* fix(keyboard): sync focusedIndex with actual DOM focus on row focus events

Co-authored-by: tiero <3596602+tiero@users.noreply.github.com>

* chore: remove accidentally committed package-lock.json

Co-authored-by: tiero <3596602+tiero@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: tiero <3596602+tiero@users.noreply.github.com>

* fix: hide virtualizer scrollbar and address review feedback

- Hide scrollbar on transaction list (reported by @Kukks)
- Remove package-lock.json from .gitignore (feedback from @pietro909)
- Remove redundant setFocusedIndex calls (CodeRabbit nitpick)

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
The app card redesign (#398) replaced the Focusable wrapper with a plain
div, losing the focus ring styling and keyboard nav flow from #283.
Re-wrap each App card in Focusable to restore focus indicator and
Enter/Space activation.
Rows with asset info (e.g. "-14.7 BB") are taller than the 61px
estimate, causing overlap. Enable measureElement so @tanstack/react-virtual
measures actual DOM heights instead of relying on the fixed estimate.
* remove tooltip from Text

* show amounts in separate line in coin list
- Switch DismissibleBanner button color from --purple to --purpletext
- Add --purpletext dark mode override (#9678f7) for better contrast
The onFocus handler on virtualised rows called setState (setFocused,
setFocusedIndex), triggering a React re-render that destroyed the
clicked DOM element before the click event completed. Convert both
to refs since they're only used in event handlers, not render output.
@pietro909
pietro909 merged commit fda01a1 into master Mar 12, 2026
7 checks passed
@bordalix
bordalix deleted the next branch May 18, 2026 16:17
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.

6 participants