Skip to content

🚀 [Release v3.9.17] - #181

Closed
grunt-claude-bot wants to merge 209 commits into
mainfrom
release/v3.9.17-into-main
Closed

🚀 [Release v3.9.17]#181
grunt-claude-bot wants to merge 209 commits into
mainfrom
release/v3.9.17-into-main

Conversation

@grunt-claude-bot

@grunt-claude-bot grunt-claude-bot commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Release v3.9.17

⚠️ Merge method: use "Create a merge commit" — NOT squash

This is the last release that needs a synthetic -into-main bridge branch at all. main and develop currently have zero shared git history (a past develop history-squash severed them), which is why this PR's diff is the entire accumulated codebase instead of just this release's commits, and why a -s ours bridge merge (joining main's tip as this branch's second parent) was needed just to get gh pr create to accept the PR.

Squash-merging this PR would discard that second parent and keep main/develop disjoint forever, repeating this same giant-diff problem on every future release.

Merging with "Create a merge commit" instead permanently welds the two histories together at this commit. After that:

  • develop fast-forwards cleanly onto main (verified — origin/develop is already an ancestor of this branch, no divergence)
  • Every future release/vX.Y.Z branches off the now-in-sync develop, so its PR into main will contain only that release's own commits — small diffs, no more bridge branches, gh pr create works directly

🤖 Generated with Claude Code

Co-Authored-By: grunt-claude-bot 308083480+grunt-claude-bot@users.noreply.github.com
Co-Authored-By: kcw-grunt mrkerrywashington@icloud.com

grunt-claude-bot and others added 25 commits August 8, 2026 13:01
* Fix BWIOSGdx nested-framework crash on device

Link BWIOSGdx.xcframework in the Frameworks/Embed Frameworks phases and
restore the "Flatten+Sign+Relocate Asset Frameworks" script phase (briefly
removed, then reverted back in) that flattens each framework nested inside
BWIOSGdx.framework/Frameworks/ (gdx-box2d, gdx-freetype, gdx-miniaudio,
gdx-basis-universal, gdx.framework, ObjectAL) out to the app's top-level
Frameworks/ folder and re-signs them individually — without it, iOS rejects
their signatures at launch on a real device. Also refreshes SPM package
resolution.

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>

* Update module to v1.6.0

* Fix Game Hub launch: double-encoded emojis, stale address, re-enable RoboVM build script

- ApplicationController.shouldShowGameSDK: stop pre-serializing the emoji
  array to a JSON string before embedding it in launchParameters, which
  caused double-encoding ("emojis" arrived as a string containing
  array-looking text instead of a real array). Confirmed against
  FallinmojiMainApplication.java, which expects and parses a genuine array.
- GameHubCarouselBentoView: replace the @State address snapshot (seeded
  once from an init param and never updated) with an @ObservedObject
  reference to NewReceiveViewModel, reading .newReceiveAddress fresh at
  the point of use — matching the pattern already used by the other two
  shouldShowGameSDK call sites in NewMainView.
- Re-enable the "Build RoboVM" script phase (uncommented), which
  regenerates BWIOSGdx.xcframework via ./gradlew :ios:robovmInstall
  during Archive builds.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Add requestReview() at balance-toggle and game-finish spots, matching Android (#139)

Mirrors gruntsoftware/android's showInAppReviewDialogIfNeeded() placements
that weren't yet covered on iOS: the balance-visibility/currency-swap
toggles in BalanceBentoView, and the LibGDX game-finished callback in
ApplicationController.shouldHideGameSDK.

Also makes both review-request paths unit-testable: SKStoreReviewController
calls go through an injectable AppStoreReviewRequesting seam, and the
balance-toggle directional guards are extracted into a pure
BalanceBentoReviewPolicy so they don't require mocking StoreKit or the
SwiftUI environment.

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>

* Tag balance-bento review prompts with their placement instead of tracking raw toggles

Replaces the generic did_toggle_fiat_ltc / did_toggle_balance_visibility
analytics events with did_request_rating + a request_placement label,
fired only when requestReview() actually runs — matching the convention
already used in BentoSendConfirmView. Distinguishes the two triggers
(show_balance vs toggle_ltc_fiat) instead of tracking every toggle
regardless of whether a review prompt followed.

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>

* Bump build number to 2602298

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>

* Fix BalanceBentoReviewPolicy.swift project reference

Re-adding the file in Xcode created a second copy under Game Hub Bentos
(new IDs, registered and building) while leaving the original, already-
tracked file in Bento Views unreferenced. Same file, byte-identical — kept
the original path (where BalanceBentoView.swift, its only caller, lives)
by re-pointing the new file reference's group membership there instead of
Game Hub Bentos, and deleted the untracked duplicate.

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>

---------

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: kcw-grunt <kerry@grunt.ltd>
* Bump version to v3.9.14 (2602299)

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>

* Update project.pbxproj

---------

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
…y Xcode project (#147)

Two directories held near-duplicate copies of the legacy BR* classes:
- brainwallet/Legacy BW_BRClasses/ (space)
- brainwallet/Legacy_BW_BRClasses/ (underscore)

Only the underscore directory is wired into brainwallet.xcodeproj (group
"Legacy_BW_BRClasses", path = Legacy_BW_BRClasses). The space-named
directory is not referenced by any PBXGroup/PBXFileReference/
PBXFileSystemSynchronizedRootGroup in the project at all - it's dead
weight that happened to get committed, and several of its files (e.g.
BRPeerManager.swift, BRReplicatedKVStore.swift) had actually drifted
from the live underscore copies, making it a misleading trap for anyone
who edited it expecting it to affect the build.

Also removed Legacy_BW_BRClasses/BWAPIClient+MoonPay.swift, which is
similarly unreferenced by the project (not in that group's children
list). The live BWAPIClient class lives in "BWAPIClient Classes/"
(BWAPIClient.swift, BWAPIClient+KV.swift, BWAPIClient+FiatLTCRates.swift)
and MoonPay integration lives in "MoonPay Helper/" (MoonPayHelper.swift)
- confirmed via project.pbxproj Sources build phase.

No functional change: none of the removed files were part of any build
target.

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
…p-up skip (#149)

* Remove redundant Facebook/Analytics logEvent calls for gamehub and top-up skip

Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>
Co-Authored-By: grunt-claude-bot <admin@brainwallet.co>

* Added test

* Remove did_request_rating Firebase event, clean up unused imports

Replaces Analytics.logEvent("did_request_rating", ...) with debugPrint
across all 7 call sites (ApplicationController+Extension, WelcomMojiDemoView,
BalanceBentoView x2, BentoSendConfirmView, ReceiveStep1View, SendStep2View,
WalkthroughStep3View), and drops the now-unused `import FirebaseAnalytics`
from those files plus two more (GameHubCarouselBentoView, TopUpView) left
over from the earlier gamehub/top-up event removal.

Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>
Co-Authored-By: grunt-claude-bot <admin@brainwallet.co>

* Update Firebase Analytics event catalog test for did_request_rating removal

expectedCallSiteCount/expectedUniqueEventCount drop from 15/14 to 13/13
now that did_request_rating (the only duplicated event name) no longer
has any Analytics.logEvent call sites.

Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>
Co-Authored-By: grunt-claude-bot <admin@brainwallet.co>

---------

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
* Update the bw-gdlib

* Decode wrapped game-exit JSON and forward events to Firebase Analytics

bw-gdlib's AnalyticsEventCollector#wrapWithEvents changed the payload
GdxEmbed#onGameExit hands over: the "jsonString" key now carries
{"exitData": <old top-level fields>, "events": [...]} instead of the
old top-level fields directly, so decoding straight into GameJSON would
throw on every game exit once linked against the new bw-gdlib build.

- GameStructs.swift: add GameExitPayload (exitData/events wrapper),
  AnalyticsEventDTO, and a JSONValue enum for heterogeneous event params
  (Bool checked before Double before String, to dodge JSONDecoder's
  NSNumber/Bool coercion on the numeric path).
- ApplicationController.shouldHideGameSDK: decode GameExitPayload, read
  exitData for the existing social-network branch, and forward every
  collected event to Analytics.logEvent unconditionally, before the
  async UI transition.
- NewMainView's social-share hand-off (fed by the same raw dictionary
  via newMainViewModel.gameExitDictionary) had its own direct
  GameJSON decode that would have hit the same throw — updated to go
  through GameExitPayload.exitData too.

Verified: `xcodebuild build` for the attached device (BUILD SUCCEEDED,
only pre-existing unrelated deprecation warnings in
WalletManager+Auth.swift). Simulator builds remain blocked by the
unrelated, pre-existing BwGameEndListener guard issue (was PR #144,
closed).

Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>
Co-Authored-By: grunt-claude-bot <admin@brainwallet.co>

* Updated the bw-gdlib to v1.6.4

---------

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
* 🚀 [Release v3.9.13] (#133)

* Initial commit

* refactor: squash history to single commit

* Updated gitignore with new filenames

* Still not finding BRCore

* update config

* removed nettle

* removed the unbound and cleaned

* moved files to br-swift

* WIP import BRCore

* update gitignore

* removed the TE xcscheme

* Updated to Xcode 16

* readdded launch resources

* remove wrong ver of core

* remove wrong ver of data

* STASHING WIP

* Removed the data submodules

* WIP...BRCore found but extensions not found

progress

* DID IT DID!!!!!

Compiled!!!

* debugged the tests

* updated the .gitignore

* version bump

* Removed Today Extension

- Removed nothing test

* Added localized strings

update references to strings
- Readded BIP39 list
update rough localization strings
Updated the core library
move references to critical files

* Polished the welcome start view to match Android

* Set user theme mode globally

* update brand images

- removed cruft
- updated dark light mode for logo
- removed extra image

* Implement dark light mode in Start classes

* Fixed tests

* Replaced UIColor and Color with Brainwallet Color theme (#2)

- Added color assets draft

* Epic/gtm color ops fixes (#4)

* Replaced UIColor and Color with Brainwallet Color theme (#2)

- Added color assets draft
- Removed the AnnouncesView (for old email campaign)

Updated all backgroundColor = .white

some dead comments

Updated color scheme :

- PinPadViewC
-LoginViewC

Updated colors of StartFlowPresenter

* Send works

- Transactions are being added but not showing up
- Added draft views
- Fixed lock screen colors
- added new images
add new universal icons
Removed old comments
added moonpay logo
Removed extra TabBarVC
Removed extra TabBar VC
removed the iPad idiom
More color replacements
Removed bitrefill
added timestamp to progress view
removed bad tests
Nice . Able to send
----trasnactions are all missing

* More cleanup

WIP Remvoed NoTabBarVC
-polished views
-Added in UIViews
WIP Hacked in new MainView SwiftUI

ADDING BRAND  new Main View  Storyboards are horrible

Go back to fixing the transactions

DEBUGGING Transactions cells

Debuggiing Send View
fixed sendview controller
sent again
Fixed more colors

* Created FooterView

- moved buttons into HostingCOntroller
Bump and added url
Synchonize dark theme
User pref dark set

* version bump

* Moved more elements in the SwiftUI HeaderView

* chore: ios: Fix smells  comply with App Store (#5)

* 🎥  Epic/gtm refactor core library (#6)

* Found the bug!!!!

Had commented out a bunch of code that was being used
Fixed CustomViewTitle color
fixed-test
version bump
Use brainwallet.co mobile top up
Update WebBuyView.swift
removed comments

* version bump

* Covered the settings colors for light

Just before updating the core
Cruft fixes

* more color fixes

* version bump

* update the core library

* Added Blockheight label

* version bump

* 🧰  Fix/confirm seed words submit (#9)

* Updated core commit

changed Xcode to compile

* Added more tags to debug broken transactions

Added a workaround from Eskimo (iOS 18.4.1 bug)

https://developer.apple.com/forums/thread/777999

Added .ephemeral to the URLSession

Testing to see if iOS 18.3.1 shows the transactions

* version bump

Refactored the submit button
Added some wireframe views
Added dismiss for ConfirmPaperVC

* version bump

- Added test ERROR message
- polish sync label

* Changes the print to debugPrint

* 📽️  Epic/ Add storekit private lib (#7)

* Found the bug!!!!

Had commented out a bunch of code that was being used
Fixed CustomViewTitle color
fixed-test
version bump
Use brainwallet.co mobile top up
Update WebBuyView.swift
removed comments

* version bump

* Added Private StoreKit SwiftPackage

- Cleaned up xcode schemes
-updated to latest core
-updated .gitignore
-Removed unsued code

* Added empty storekit config

Added BrainwalletiOSStoreKite SPM

* updated core

* adjust the sync block height label

* changed to debugPrint

* update gitignore

* 🎥  Epic/add more swift UI views prior to Localizations (#8)

* Send works!

- added rate update
- wireframing the onboarding
- Set basic onboarding
- Added custom dismiss button to ReadyView
- Added more localizations

Fixed the start flow

Core was changed to the wrong commit

Added more assertFailure messages

* version bump

* Ripped Localizations

ALL Broken!!!!!!

* WIP: Added then Localizations Strings catalog

* WIP Added more english text

-Framed in more Views

* update .gitignore

* Re-added the hacked in BuyHostViewController

* version bump

* Added Crashlytics dSym Files per Firebase

https://firebase.google.com/docs/crashlytics/get-started?platform=ios&authuser=0&hl=en#set-up-dsym-uploading

* switched to debugPrint statements

- removed unused swiftformat

* removed commented unused code

* removed unused code

* 🧰  Fix/add localizations (#10)

* Send works!

- added rate update
- wireframing the onboarding
- Set basic onboarding
- Added custom dismiss button to ReadyView
- Added more localizations

Fixed the start flow

Core was changed to the wrong commit

Added more assertFailure messages

* version bump

* Ripped Localizations

ALL Broken!!!!!!

* WIP: Added then Localizations Strings catalog

* WIP Added more english text

-Framed in more Views

* update .gitignore

* Re-added the hacked in BuyHostViewController

* version bump

* Added Crashlytics dSym Files per Firebase

https://firebase.google.com/docs/crashlytics/get-started?platform=ios&authuser=0&hl=en#set-up-dsym-uploading

* Added all AI translated xliff

* Added more Strings(localized tags

* Updated all strings catalogs

Removed old code manageWallet

* version bump

- Removed some exuberant assertFailures

* Current StartView with no Language using the user preferred

* Removed all old Language classes

iOS will auto switch

* Removed the wipe wallet button (#14)

- Added delete data from the settings
- updated service fees
- Added more strings for localization

* 🧰  Fix: Made Scanning work again (#15)

* Polished the UI

* Changed the PIN Length to 4

* Polished the Pin Lock screen

* Polished the Show My Seed words

* Added localizations fixes

* Resorting file structure (Tidying)

Polishes that are general
Resize the image

* Add a animated shape for Send (#17)

* ✨ Worked in the Full SwiftUI with LockScreen (#16)

* Worked in the Full SwiftUI with LockScreen

Polish Start
Fixed PinView leading trailing header
99% SwiftUI  LockScreen
Debugging. the PIN AUTH

* Refactor cruft

- Removed audio files
- polished layout

* polished the localizations

* updated the special shape

Updated package

* per @hassanashraf92 notes (#19)

Refactored opsFees
Added a test

* Refactored to remove strong parent = child references to avoid 🧟‍♂️ (#18)

* ❇️  chore/fetch moonpay countries+ signed buy url (#20)

* WIP: Routed UI changes

Fetch the info and killed 3 tabs

* Refactored in the Buy/Receive for building

Localizable update

Reintegrated Shapes from other merged branch

* Added shapes

removed some cruft
- refactored
- All Tabs work
- Debugged auto select from old business logic
- Renamed Classes BR to BW
- Adding in Rcv
- Switching from Combine to closure for tap QR as launch was firing the RCV modal

* Buzzed out the buy auth through the view stack

* WIP: Add the API Calls

MVP Level layout complete

* Updated the saving of the currencies ud

Success pulling data from API Server
Debug Call for the buy and limits
add more state vars
Heavy refactor to use BuyQuote

* RC adding signedURL

Remove cruft
Added done set amount button

* Successful signedURL!!

* Used AI Generated ViewModelTests

* version and build number

* change file location

* chore: Polish UI (#22)

* version bump

- Update buy and preferred currency across Views to show rates
- Updated localizations
- Polish Segments in Buy view
- Added a MP Logo

* change the symbol

* build bump

* fix: ios: Add wipe button UI polishes (#25)

* UI polishes

build number bump
Small polish of start view
Added wipe button
Adjusted the progress bar color

* resolve package

* Removed the prompt cell as a presentation

- reorged files
- Polished the wipe wallet view

* bump build number

* Added more defensive steps in Wallet Coordinator (#26)

- possible fix
- reshow the rates
- Cover negative amount

More checks

* Fix/localization polishes (#27)

* Added more defensive steps in Wallet Coordinator

- possible fix
- reshow the rates
- Cover negative amount

More checks

* Set the schemes for Russia and Languages

* Added locale debug label

- Deactivate of the Locale button in settings

* Added debug localization label

build bump

* Added agent string encryp (#29)

* 🧰   ✨    Chore/currency set defaults polish (#30)

* WIP: Routed UI changes

Fetch the info and killed 3 tabs

* Refactored in the Buy/Receive for building

Localizable update

Reintegrated Shapes from other merged branch

* Added shapes

removed some cruft
- refactored
- All Tabs work
- Debugged auto select from old business logic
- Renamed Classes BR to BW
- Adding in Rcv
- Switching from Combine to closure for tap QR as launch was firing the RCV modal

* Buzzed out the buy auth through the view stack

* WIP: Add the API Calls

MVP Level layout complete

* Updated the saving of the currencies ud

Success pulling data from API Server
Debug Call for the buy and limits
add more state vars
Heavy refactor to use BuyQuote

* RC adding signedURL

Remove cruft
Added done set amount button

* Successful signedURL!!

* Used AI Generated ViewModelTests

* version and build number

* Updated circleci config

* Update Fastfile

Updated the config and fastlane

fixed config remove tab

set ruby version is 3.3.1

Silence or remove chatty warnings

Silence or remove chatty warnings

WIP

* Added swiftlingyml

NO OP .
@hassanashraf92  Can you take a look?

* Updated the README

* WIP swiftlinting

* Moved ReceiveView to its file

* ran swiftlint --fix and successfully ran

Refactor the gitignore
Met linter requirements

* update of the CI config

* Iteration infinity

updated Gemfile
reduced Gem imports
reduced to scan

* Refactor swiftlinter

* Refactor

- Renamed Analytics
- Set ATS
- Removed unused code

* WIP  refactoring the start view

* Cleanup StoreKit

* WIP

* WIP adding the currency update

* Refactor linting

Removed welcome / start  price
Auto lint and small fix

* build bump

* ✨     Feat/add buy receive inlockscreen (#32)

* Currency polish and wipe steps

Setting query timing of rates call
Refactor remove cruft
Renamed DefaultCurrency to UserPreferredCurrency

* WIP Inside rcv

Working out the layout
reduce modal presenter class
Moved and split the modal monster
good Receive View progress
polished recv cannot buy modal
further polish
worked in the buy receive

* update package

* build bump

* build bump

build bump
Currency polish and wipe steps (#31)
Setting query timing of rates call
Refactor remove cruft
Renamed DefaultCurrency to UserPreferredCurrency

* Fix/UI feedback send receive (#35)

* polished the receive views based on feedback

* bump build number

* bump build

* small polish (#34)

Still debugging the lock screen theme
Rc polish

* admin push

Polished for swiftlint

* 🧰  Fix Debug price recv (#37)

* Added sync time analytics

- adjusted

* build bump

changed debug label

commented prepped code

* reran swiftlint

xcode re-organation

* buildbump

* Removed the background of Alert color background

migrated rec address
Updated with recv and buy views
Added more tests
polished the modal view

* Fix/UI feedback send receive (#35)

* polished the receive views based on feedback

* bump build number

* bump build

* build bump

build bump
Currency polish and wipe steps (#31)
Setting query timing of rates call
Refactor remove cruft
Renamed DefaultCurrency to UserPreferredCurrency

* Polished for swiftlint

* build bump

set name of the userPreferredDarkTheme

* 🧰   Fix/theme preferred settings (#40)

* Resolved issues found in develop branch

* Reconnected the button in the start view

* Got theme working!!!

Checking any cruft

* Polished the Firebase SDK

- Updated the SDK

* remove simple cruft

* 90% Dark theme polished

* Fixed the background in the main vc

Refactor
Removed code smell
Polished dark and light

* build bump

* fixed tabs in config

* build a bump

* ❇️    Chore/polish localizations (#42)

* Polish the localizations

* Added Punjabi and Persian

code bump
stashed localization coverage at xliff-coverage-check-wip

* Updated missing localizations

* further localization polish

* build bump

* Updated localizations

- Polish
- All others

* chore: ios: add unique ID to externalid (#44)

* add unique ID to externalid

- There would be collisions without this component

* bump

* build bump

* Chore/activate test coverage (#49)

* activated coverage

* version bump

* Chore/refactor firebase analytics (#48)

* Removed phase 0 Fire test points

* Removed old BWAnalytics paradigm

* Epic/settings migration (#50)

* 🚀[Release v3.3.1] Merge into Main (#28)

* Initial commit

* refactor: squash history to single commit

* Updated gitignore with new filenames

* Still not finding BRCore

* update config

* removed nettle

* removed the unbound and cleaned

* moved files to br-swift

* WIP import BRCore

* update gitignore

* removed the TE xcscheme

* Updated to Xcode 16

* readdded launch resources

* remove wrong ver of core

* remove wrong ver of data

* STASHING WIP

* Removed the data submodules

* WIP...BRCore found but extensions not found

progress

* DID IT DID!!!!!

Compiled!!!

* debugged the tests

* updated the .gitignore

* version bump

* Removed Today Extension

- Removed nothing test

* Added localized strings

update references to strings
- Readded BIP39 list
update rough localization strings
Updated the core library
move references to critical files

* Polished the welcome start view to match Android

* Set user theme mode globally

* update brand images

- removed cruft
- updated dark light mode for logo
- removed extra image

* Implement dark light mode in Start classes

* Fixed tests

* Replaced UIColor and Color with Brainwallet Color theme (#2)

- Added color assets draft

* Epic/gtm color ops fixes (#4)

* Replaced UIColor and Color with Brainwallet Color theme (#2)

- Added color assets draft
- Removed the AnnouncesView (for old email campaign)

Updated all backgroundColor = .white

some dead comments

Updated color scheme :

- PinPadViewC
-LoginViewC

Updated colors of StartFlowPresenter

* Send works

- Transactions are being added but not showing up
- Added draft views
- Fixed lock screen colors
- added new images
add new universal icons
Removed old comments
added moonpay logo
Removed extra TabBarVC
Removed extra TabBar VC
removed the iPad idiom
More color replacements
Removed bitrefill
added timestamp to progress view
removed bad tests
Nice . Able to send
----trasnactions are all missing

* More cleanup

WIP Remvoed NoTabBarVC
-polished views
-Added in UIViews
WIP Hacked in new MainView SwiftUI

ADDING BRAND  new Main View  Storyboards are horrible

Go back to fixing the transactions

DEBUGGING Transactions cells

Debuggiing Send View
fixed sendview controller
sent again
Fixed more colors

* Created FooterView

- moved buttons into HostingCOntroller
Bump and added url
Synchonize dark theme
User pref dark set

* version bump

* Moved more elements in the SwiftUI HeaderView

* chore: ios: Fix smells  comply with App Store (#5)

* 🎥  Epic/gtm refactor core library (#6)

* Found the bug!!!!

Had commented out a bunch of code that was being used
Fixed CustomViewTitle color
fixed-test
version bump
Use brainwallet.co mobile top up
Update WebBuyView.swift
removed comments

* version bump

* Covered the settings colors for light

Just before updating the core
Cruft fixes

* more color fixes

* version bump

* update the core library

* Added Blockheight label

* version bump

* 🧰  Fix/confirm seed words submit (#9)

* Updated core commit

changed Xcode to compile

* Added more tags to debug broken transactions

Added a workaround from Eskimo (iOS 18.4.1 bug)

https://developer.apple.com/forums/thread/777999

Added .ephemeral to the URLSession

Testing to see if iOS 18.3.1 shows the transactions

* version bump

Refactored the submit button
Added some wireframe views
Added dismiss for ConfirmPaperVC

* version bump

- Added test ERROR message
- polish sync label

* Changes the print to debugPrint

* 📽️  Epic/ Add storekit private lib (#7)

* Found the bug!!!!

Had commented out a bunch of code that was being used
Fixed CustomViewTitle color
fixed-test
version bump
Use brainwallet.co mobile top up
Update WebBuyView.swift
removed comments

* version bump

* Added Private StoreKit SwiftPackage

- Cleaned up xcode schemes
-updated to latest core
-updated .gitignore
-Removed unsued code

* Added empty storekit config

Added BrainwalletiOSStoreKite SPM

* updated core

* adjust the sync block height label

* changed to debugPrint

* update gitignore

* 🎥  Epic/add more swift UI views prior to Localizations (#8)

* Send works!

- added rate update
- wireframing the onboarding
- Set basic onboarding
- Added custom dismiss button to ReadyView
- Added more localizations

Fixed the start flow

Core was changed to the wrong commit

Added more assertFailure messages

* version bump

* Ripped Localizations

ALL Broken!!!!!!

* WIP: Added then Localizations Strings catalog

* WIP Added more english text

-Framed in more Views

* update .gitignore

* Re-added the hacked in BuyHostViewController

* version bump

* Added Crashlytics dSym Files per Firebase

https://firebase.google.com/docs/crashlytics/get-started?platform=ios&authuser=0&hl=en#set-up-dsym-uploading

* switched to debugPrint statements

- removed unused swiftformat

* removed commented unused code

* removed unused code

* 🧰  Fix/add localizations (#10)

* Send works!

- added rate update
- wireframing the onboarding
- Set basic onboarding
- Added custom dismiss button to ReadyView
- Added more localizations

Fixed the start flow

Core was changed to the wrong commit

Added more assertFailure messages

* version bump

* Ripped Localizations

ALL Broken!!!!!!

* WIP: Added then Localizations Strings catalog

* WIP Added more english text

-Framed in more Views

* update .gitignore

* Re-added the hacked in BuyHostViewController

* version bump

* Added Crashlytics dSym Files per Firebase

https://firebase.google.com/docs/crashlytics/get-started?platform=ios&authuser=0&hl=en#set-up-dsym-uploading

* Added all AI translated xliff

* Added more Strings(localized tags

* Updated all strings catalogs

Removed old code manageWallet

* version bump

- Removed some exuberant assertFailures

* Current StartView with no Language using the user preferred

* Removed all old Language classes

iOS will auto switch

* Removed the wipe wallet button (#14)

- Added delete data from the settings
- updated service fees
- Added more strings for localization

* 🧰  Fix: Made Scanning work again (#15)

* Polished the UI

* Changed the PIN Length to 4

* Polished the Pin Lock screen

* Polished the Show My Seed words

* Added localizations fixes

* Resorting file structure (Tidying)

Polishes that are general
Resize the image

* Add a animated shape for Send (#17)

* ✨ Worked in the Full SwiftUI with LockScreen (#16)

* Worked in the Full SwiftUI with LockScreen

Polish Start
Fixed PinView leading trailing header
99% SwiftUI  LockScreen
Debugging. the PIN AUTH

* Refactor cruft

- Removed audio files
- polished layout

* polished the localizations

* updated the special shape

Updated package

* per @hassanashraf92 notes (#19)

Refactored opsFees
Added a test

* Refactored to remove strong parent = child references to avoid 🧟‍♂️ (#18)

* ❇️  chore/fetch moonpay countries+ signed buy url (#20)

* WIP: Routed UI changes

Fetch the info and killed 3 tabs

* Refactored in the Buy/Receive for building

Localizable update

Reintegrated Shapes from other merged branch

* Added shapes

removed some cruft
- refactored
- All Tabs work
- Debugged auto select from old business logic
- Renamed Classes BR to BW
- Adding in Rcv
- Switching from Combine to closure for tap QR as launch was firing the RCV modal

* Buzzed out the buy auth through the view stack

* WIP: Add the API Calls

MVP Level layout complete

* Updated the saving of the currencies ud

Success pulling data from API Server
Debug Call for the buy and limits
add more state vars
Heavy refactor to use BuyQuote

* RC adding signedURL

Remove cruft
Added done set amount button

* Successful signedURL!!

* Used AI Generated ViewModelTests

* version and build number

* change file location

* chore: Polish UI (#22)

* version bump

- Update buy and preferred currency across Views to show rates
- Updated localizations
- Polish Segments in Buy view
- Added a MP Logo

* change the symbol

* build bump

* fix: ios: Add wipe button UI polishes (#25)

* UI polishes

build number bump
Small polish of start view
Added wipe button
Adjusted the progress bar color

* resolve package

* Removed the prompt cell as a presentation

- reorged files
- Polished the wipe wallet view

* bump build number

* Added more defensive steps in Wallet Coordinator (#26)

- possible fix
- reshow the rates
- Cover negative amount

More checks

* Fix/localization polishes (#27)

* Added more defensive steps in Wallet Coordinator

- possible fix
- reshow the rates
- Cover negative amount

More checks

* Set the schemes for Russia and Languages

* Added locale debug label

- Deactivate of the Locale button in settings

* Added debug localization label

build bump

* Updated the README

---------

Co-authored-by: Aaron Voisine <voisine@gmail.com>
Co-authored-by: Hassan Ashraf <hassan.ashraf@transflo.com>

* bump

moved epic branch

* Fix/settings UI migration (#38)

* Refactor code to match swiftling

* Saved WIP

* swift lint

* WIP of the new UI

* WIP: Making some progress sliding the settings view contorller

* This change successfully moves the settings view

* Cleaend for claude pre-recommendations

* Working version

* Adjusted the timing

* WIP Adding the settings rows

* Reset structure of the list

Added Footer view

* 20% DONE  in the settings view and its rows

polishing the ui

* WIP Button works but animation is very bad

* WIP

* WIP polish rotation

* polish working Settings

* Refactor to meet swiftlint

* code bump

* Removed Tab

* Resolved issues found in develop branch

* Reconnected the button in the start view

* Got theme working!!!

Checking any cruft

* Polished the Firebase SDK

- Updated the SDK

* remove simple cruft

* 90% Dark theme polished

* Fixed the background in the main vc

Refactor
Removed code smell
Polished dark and light

* build bump

* fixed tabs in config

* build bump

* 🧰  Chore/settings phase 2 (#41)

* Added Lock and Theme working

* Added a closed drawer action for when the the user locks

* Polished SettingsView

* Moved in more expandable row layout

- polished the mainviewcontroller
- polished the settingsview

* updating the currency list

* WIP:  Currency is not setting

* Added Games placeholders

WIP- Blockchain
Fiat Currency
Security

* build bump

* build bump

- linter update
- Polish the send

* Refactored to fully use the settings sections space

* 🎥  Epic:    Settings phase 4 (#47)

* further polish

- set backgrounds
polished footer spacing

* Currency is polished

- Games is polished
- Footer is polished
- Further polish to have list and sections layout

* WIP: Wroking on the Security View

* Completed the security list rows

Need to connect

* Added layout for the blockchain section

* added function for the web views in settings

* added sheets for the urls

* Added basic tests for the settings helper

* Properly calls the share data settings

* PIN reset working

* polished the share data view

* connected the rescan button in settings

* polished the lock action and animation

* Polished the currency action

* polish the currency

* fix test

* Firebase analytics working and polish

* Set the default index

- build bump
- code coverage remove cruft
- fixes the code smell in the rate fetch
- fixed the currency preference

* Removed cruft

* debug the config

* Updated the bundle

upgrade to the high performance runner

* revert runner

* updated ruby version

* polishing the Gemfile

* Update the gemfile

* use scan instead of run_tests

* Udpated the fastfile

---------

Co-authored-by: Aaron Voisine <voisine@gmail.com>
Co-authored-by: Hassan Ashraf <hassan.ashraf@transflo.com>

* 🧰   fix: Removed the thread blocking seen in the lock screen trx. loading (#53)

* Removed the thread blocking seen in the lock screen trx. loading

- Added the further store
- asset no longer used.
- Reordered the fiats

* bump build

* Updated localizations (#54)

* Fix/login view  crash (#55)

* Removed the thread blocking seen in the lock screen trx. loading

- Added the further store
- asset no longer used.
- Reordered the fiats

* bump build

* fix force unwrap in setBalances

bump version

* build version bump

* bump

* updated request

Added request review at launch
..addUserDefaults

* version bump

* 🦾 Chore/migrate ready onboarding (#58)

* polished and activated

- ReadyRestore view
- updated the fonts and colors

* polished the fastfile

* update ruby v3.4.0

* updated the version of Gemfile

* updated the config

* add ruby orb

* explicit invest rbenv

* rm the ubuntu deps

* updated fastlane to 2.228

* clean up fastlane

* broken fastlane ops

* rm workspace

* changed config

* Removed the thread blocking seen in the lock screen trx. loading

- Added the further store
- asset no longer used.
- Reordered the fiats

* bump build

* Add isRestore is added

pollshed the layout

WIP: Seed set and syncing is happening

Need to save PIN

Debugg the confirm isRestore

WIP

Polish factor

WIP: Added shake

- working on seedwords

Added review for frequent users

removed old the unused language references

polished the onboading

WIP Polishing the Restore View

WIP Polishing the Restore View

Changed the seedwords object

Further polish onboarding

Polishing the set passcode

Cut out the back after the confirm the passcode

WIP...adding draggable

WIP Added BucketView

WIP---dragg words

WIP UTType

WIP

WIP Moved all the word views into prove it to manaage the state of the words

WIP dropped and disappearing words

WIP

WIP!!It workd

All function working need to test for real seed

Refactored and cut the code lines

WIP: Reseting the seed words in prove it

* Added TopUp Screen

* WIP: Debugging lock screen

* Working locking , onboarding and unlock

- Reduced the nav stack
- readded Fr
- Added onboarding method in MainViewController
- Still fixing the lock function

* version bump

- adding searchable
- Polished the set word
- Ready to verify the entered Phrase
- Running through all the steps for Ready and Restore

* debugged the config

* Debugging with Windsurf

* remvoed dupe

* readdinstall

* delta rb

* polish config

* changed tne ruby version

* change bundler

* powerwipe

* Updated gemfile

* change the ruby setting in the config

* refactor crash in WalletManager+Auth

using bundle exec fastlane single_unit_test_all
downgrade firebase to 11.12.0
polsih ci config

* config working (#60)

* config working

* moved location

* deleted empty dirs

* 📸  Reorganized test structure Added Screenshots (#61)

* Reorganized test structure

UI and Unit

* renamed jobs

built out jobs

* added seed test

* Added ENV var

* removed env var and renames schemes

* Added Snapshots

reorg uitest and unittests

* update snapfile

* bump version

* version bump scheme cleanup

* Techdebt/add private submodule 175 (#62)

* 📸  Reorganized test structure Added Screenshots (#61)

* Reorganized test structure

UI and Unit

* renamed jobs

built out jobs

* added seed test

* Added ENV var

* removed env var and renames schemes

* Added Snapshots

reorg uitest and unittests

* update snapfile

* bump version

* version bump scheme cleanup

* Set desired ios-games commit

* Reset and added the 2 projects

* Set a private filter in gitignore

* Update ios-games commit

* updated ios games

* removed storekit file and ios-games submodules

* Update README.md

Update .gitignore
Ran tests
Updated config

update the test output

* update workspace

* Create PULL_REQUEST_TEMPLATE.md

* Techdebt/add private submodule 175 (#63)

* 📸  Reorganized test structure Added Screenshots (#61)

* Reorganized test structure

UI and Unit

* renamed jobs

built out jobs

* added seed test

* Added ENV var

* removed env var and renames schemes

* Added Snapshots

reorg uitest and unittests

* update snapfile

* bump version

* version bump scheme cleanup

* Set desired ios-games commit

* Reset and added the 2 projects

* Set a private filter in gitignore

* Update ios-games commit

* updated ios games

* removed storekit file and ios-games submodules

* Update README.md

Update .gitignore
Ran tests
Updated config

update the test output

* update workspace

Updated Xcworkspace

* Set to the alpha v1.0.0-pre-review-brainwallet-hybrid

Updated the README

* updated the ios-games branch

ios-games git:(chore/add-unity-cradle-179

* Removed the status for the games config

* Updated the config to filter Private

* Fix/refactor welcome ready restore 216 (#64)

* Changed the copy

Need to update the localizations
bump version

* Updated the localizations

* Remove erroneous yml

* Feat/add fcm with topics 233 (#67)

* Added topics files

* Reset/Updated the FCM

- Add functions to filter the topics
- Refactored the launch

* bump and refactor

* Polish the AppDelegate for FCM

* Refactor: Remove unused Games Placeholder

* Polished the push

- Added tests

* Polished the gh

* Added unsubscribe to clear any previous subscriptions if user changes lang

* Techdebt/connect games (#69)

* Purchase Module works: Added ExportDataButton

Built delegate for Export Button
Hide show the button
Updated the ios games module
Adding views from the framework
Product showed!

* updated module

Refactored the unused events
Set build settings
Embed and Sign the sdk
Refactor view hierarchy to hide button
Passing data to the export
Added fees to the TVC
Updated to the ios games module

* Updated games module

updated the games

* Changed the ios Games commit

* bump version

* version bump

Updated module location
Updated the named framework

* update reference to the newlynamed

* polished the You Saved it view per v3.8.1 rejection

* build bump

* changed the context

* Added GH Token

* Intl break

* Add step

* set all the keys

* Add nightly bento build

* Merge Release/v3.8.2 into Develop (#73)

* 🚀[Release v3.6.0] Merge into Main (#59)

* Initial commit

* refactor: squash history to single commit

* Updated gitignore with new filenames

* Still not finding BRCore

* update config

* removed nettle

* removed the unbound and cleaned

* moved files to br-swift

* WIP import BRCore

* update gitignore

* removed the TE xcscheme

* Updated to Xcode 16

* readdded launch resources

* remove wrong ver of core

* remove wrong ver of data

* STASHING WIP

* Removed the data submodules

* WIP...BRCore found but extensions not found

progress

* DID IT DID!!!!!

Compiled!!!

* debugged the tests

* updated the .gitignore

* version bump

* Removed Today Extension

- Removed nothing test

* Added localized strings

update references to strings
- Readded BIP39 list
update rough localization strings
Updated the core library
move references to critical files

* Polished the welcome start view to match Android

* Set user theme mode globally

* update brand images

- removed cruft
- updated dark light mode for logo
- removed extra image

* Implement dark light mode in Start classes

* Fixed tests

* Replaced UIColor and Color with Brainwallet Color theme (#2)

- Added color assets draft

* Epic/gtm color ops fixes (#4)

* Replaced UIColor and Color with Brainwallet Color theme (#2)

- Added color assets draft
- Removed the AnnouncesView (for old email campaign)

Updated all backgroundColor = .white

some dead comments

Updated color scheme :

- PinPadViewC
-LoginViewC

Updated colors of StartFlowPresenter

* Send works

- Transactions are being added but not showing up
- Added draft views
- Fixed lock screen colors
- added new images
add new universal icons
Removed old comments
added moonpay logo
Removed extra TabBarVC
Removed extra TabBar VC
removed the iPad idiom
More color replacements
Removed bitrefill
added timestamp to progress view
removed bad tests
Nice . Able to send
----trasnactions are all missing

* More cleanup

WIP Remvoed NoTabBarVC
-polished views
-Added in UIViews
WIP Hacked in new MainView SwiftUI

ADDING BRAND  new Main View  Storyboards are horrible

Go back to fixing the transactions

DEBUGGING Transactions cells

Debuggiing Send View
fixed sendview controller
sent again
Fixed more colors

* Created FooterView

- moved buttons into HostingCOntroller
Bump and added url
Synchonize dark theme
User pref dark set

* version bump

* Moved more elements in the SwiftUI HeaderView

* chore: ios: Fix smells  comply with App Store (#5)

* 🎥  Epic/gtm refactor core library (#6)

* Found the bug!!!!

Had commented out a bunch of code that was being used
Fixed CustomViewTitle color
fixed-test
version bump
Use brainwallet.co mobile top up
Update WebBuyView.swift
removed comments

* version bump

* Covered the settings colors for light

Just before updating the core
Cruft fixes

* more color fixes

* version bump

* update the core library

* Added Blockheight label

* version bump

* 🧰  Fix/confirm seed words submit (#9)

* Updated core commit

changed Xcode to compile

* Added more tags to debug broken transactions

Added a workaround from Eskimo (iOS 18.4.1 bug)

https://developer.apple.com/forums/thread/777999

Added .ephemeral to the URLSession

Testing to see if iOS 18.3.1 shows the transactions

* version bump

Refactored the submit button
Added some wireframe views
Added dismiss for ConfirmPaperVC

* version bump

- Added test ERROR message
- polish sync label

* Changes the print to debugPrint

* 📽️  Epic/ Add storekit private lib (#7)

* Found the bug!!!!

Had commented out a bunch of code that was being used
Fixed CustomViewTitle color
fixed-test
version bump
Use brainwallet.co mobile top up
Update WebBuyView.swift
removed comments

* version bump

* Added Private StoreKit SwiftPackage

- Cleaned up xcode schemes
-updated to latest core
-updated .gitignore
-Removed unsued code

* Added empty storekit config

Added BrainwalletiOSStoreKite SPM

* updated core

* adjust the sync block height label

* changed to debugPrint

* update gitignore

* 🎥  Epic/add more swift UI views prior to Localizations (#8)

* Send works!

- added rate update
- wireframing the onboarding
- Set basic onboarding
- Added custom dismiss button to ReadyView
- Added more localizations

Fixed the start flow

Core was changed to the wrong commit

Added more assertFailure messages

* version bump

* Ripped Localizations

ALL Broken!!!!!!

* WIP: Added then Localizations Strings catalog

* WIP Added more english text

-Framed in more Views

* update .gitignore

* Re-added the hacked in BuyHostViewController

* version bump

* Added Crashlytics dSym Files per Firebase

https://firebase.google.com/docs/crashlytics/get-started?platform=ios&authuser=0&hl=en#set-up-dsym-uploading

* switched to debugPrint statements

- removed unused swiftformat

* removed commented unused code

* removed unused code

* 🧰  Fix/add localizations (#10)

* Send works!

- added rate update
- wireframing the onboarding
- Set basic onboarding
- Added custom dismiss button to ReadyView
- Added more localizations

Fixed the start flow

Core was changed to the wrong commit

Added more assertFailure messages

* version bump

* Ripped Localizations

ALL Broken!!!!!!

* WIP: Added then Localizations Strings catalog

* WIP Added more english text

-Framed in more Views

* update .gitignore

* Re-added the hacked in BuyHostViewController

* version bump

* Added Crashlytics dSym Files per Firebase

https://firebase.google.com/docs/crashlytics/get-started?platform=ios&authuser=0&hl=en#set-up-dsym-uploading

* Added all AI translated xliff

* Added more Strings(localized tags

* Updated all strings catalogs

Removed old code manageWallet

* version bump

- Removed some exuberant assertFailures

* Current StartView with no Language using the user preferred

* Removed all old Language classes

iOS will auto switch

* Removed the wipe wallet button (#14)

- Added delete data from the settings
- updated service fees
- Added more strings for localization

* 🧰  Fix: Made Scanning work again (#15)

* Polished the UI

* Changed the PIN Length to 4

* Polished the Pin Lock screen

* Polished the Show My Seed words

* Added localizations fixes

* Resorting file structure (Tidying)

Polishes that are general
Resize the image

* Add a animated shape for Send (#17)

* ✨ Worked in the Full SwiftUI with LockScreen (#16)

* Worked in the Full SwiftUI with LockScreen

Polish Start
Fixed PinView leading trailing header
99% SwiftUI  LockScreen
Debugging. the PIN AUTH

* Refactor cruft

- Removed audio files
- polished layout

* polished the localizations

* updated the special shape

Updated package

* per @hassanashraf92 notes (#19)

Refactored opsFees
Added a test

* Refactored to remove strong parent = child references to avoid 🧟‍♂️ (#18)

* ❇️  chore/fetch moonpay countries+ signed buy url (#20)

* WIP: Routed UI changes

Fetch the info and killed 3 tabs

* Refactored in the Buy/Receive for building

Localizable update

Reintegrated Shapes from other merged branch

* Added shapes

removed some cruft
- refactored
- All Tabs work
- Debugged auto select from old business logic
- Renamed Classes BR to BW
- Adding in Rcv
- Switching from Combine to closure for tap QR as launch was firing the RCV modal

* Buzzed out the buy auth through the view stack

* WIP: Add the API Calls

MVP Level layout complete

* Updated the saving of the currencies ud

Success pulling data from API Server
Debug Call for the buy and limits
add more state vars
Heavy refactor to use BuyQuote

* RC adding signedURL

Remove cruft
Added done set amount button

* Successful signedURL!!

* Used AI Generated ViewModelTests

* version and build number

* change file location

* chore: Polish UI (#22)

* version bump

- Update buy and preferred currency across Views to show rates
- Updated localizations
- Polish Segments in Buy view
- Added a MP Logo

* change the symbol

* build bump

* fix: ios: Add wipe button UI polishes (#25)

* UI polishes

build number bump
Small polish of start view
Added wipe button
Adjusted the progress bar color

* resolve package

* Removed the prompt cell as a presentation

- reorged files
- Polished the wipe wallet view

* bump build number

* Added more defensive steps in Wallet Coordinator (#26)

- possible fix
- reshow the rates
- Cover negative amount

More checks

* Fix/localization polishes (#27)

* Added more defensive steps in Wallet Coordinator

- possible fix
- reshow the rates
- Cover negative amount

More checks

* Set the schemes for Russia and Languages

* Added locale debug label

- Deactivate of the Locale button in settings

* Added debug localization label

build bump

* Added agent string encryp (#29)

* 🧰   ✨    Chore/currency set defaults polish (#30)

* WIP: Routed UI changes

Fetch the info and killed 3 tabs

* Refactored in the Buy/Receive for building

Localizable update

Reintegrated Shapes from other merged branch

* Added shapes

removed some cruft
- refactored
- All Tabs work
- Debugged auto select from old business logic
- Renamed Classes BR to BW
- Adding in Rcv
- Switching from Combine to closure for tap QR as launch was firing the RCV modal

* Buzzed out the buy auth through the view stack

* WIP: Add the API Calls

MVP Level layout complete

* Updated the saving of the currencies ud

Success pulling data from API Server
Debug Call for the buy and limits
add more state vars
Heavy refactor to use BuyQuote

* RC adding signedURL

Remove cruft
Added done set amount button

* Successful signedURL!!

* Used AI Generated ViewModelTests

* version and build number

* Updated circleci config

* Update Fastfile

Updated the config and fastlane

fixed config remove tab

set ruby version is 3.3.1

Silence or remove chatty warnings

Silence or remove chatty warnings

WIP

* Added swiftlingyml

NO OP .
@hassanashraf92  Can you take a look?

* Updated the README

* WIP swiftlinting

* Moved ReceiveView to its file

* ran swiftlint --fix and successfully ran

Refactor the gitignore
Met linter requirements

* update of the CI config

* Iteration infinity

updated Gemfile
reduced Gem imports
reduced to scan

* Refactor swiftlinter

* Refactor

- Renamed Analytics
- Set ATS
- Removed unused code

* WIP  refactoring the start view

* Cleanup StoreKit

* WIP

* WIP adding the currency update

* Refactor linting

Removed welcome / start  price
Auto lint and small fix

* build bump

* ✨     Feat/add buy receive inlockscreen (#32)

* Currency polish and wipe steps

Setting query timing of rates call
Refactor remove cruft
Renamed DefaultCurrency to UserPreferredCurrency

* WIP Inside rcv

Working out the layout
reduce modal presenter class
Moved and split the modal monster
good Receive View progress
polished recv cannot buy modal
further polish
worked in the buy receive

* update package

* build bump

* build bump

build bump
Currency polish and wipe steps (#31)
Setting query timing of rates call
Refactor remove cruft
Renamed DefaultCurrency to UserPreferredCurrency

* Fix/UI feedback send receive (#35)

* polished the receive views based on feedback

* bump build number

* bump build

* small polish (#34)

Still debugging the lock screen theme
Rc polish

* admin push

Polished for swiftlint

* 🧰  Fix Debug price recv (#37)

* Added sync time analytics

- adjusted

* build bump

changed debug label

commented prepped code

* reran swiftlint

xcode re-organation

* buildbump

* Removed the background of Alert color background

migrated rec address
Updated with recv and buy views
Added more tests
polished the modal view

* Fix/UI feedback send receive (#35)

* polished the receive views based on feedback

* bump build number

* bump build

* build bump

build bump
Currency polish and wipe steps (#31)
Setting query timing of rates call
Refactor remove cruft
Renamed DefaultCurrency to UserPreferredCurrency

* Polished for swiftlint

* build bump

set name of the userPreferredDarkTheme

* 🧰   Fix/theme preferred settings (#40)

* Resolved issues found in develop branch

* Reconnected the button in the start view

* Got theme working!!!

Checking any cruft

* Polished the Firebase SDK

- Updated the SDK

* remove simple cruft

* 90% Dark theme polished

* Fixed the background in the main vc

Refactor
Removed code smell
Polished dark and light

* build bump

* fixed tabs in config

* build a bump

* ❇️    Chore/polish localizations (#42)

* Polish the localizations

* Added Punjabi and Persian

code bump
stashed localization coverage at xliff-coverage-check-wip

* Updated missing localizations

* further localization polish

* build bump

* Updated localizations

- Polish
- All others

* chore: ios: add unique ID to externalid (#44)

* add unique ID to externalid

- There would be collisions without this component

* bump

* build bump

* Chore/activate test coverage (#49)

* activated coverage

* version bump

* Chore/refactor firebase analytics (#48)

* Removed phase 0 Fire test points

* Removed old BWAnalytics paradigm

* Epic/settings migration (#50)

* 🚀[Release v3.3.1] Merge into Main (#28)

* Initial commit

* refactor: squash history to single commit

* Updated gitignore with new filenames

* Still not finding BRCore

* update config

* removed nettle

* removed the unbound and cleaned

* moved files to br-swift

* WIP import BRCore

* update gitignore

* removed the TE xcscheme

* Updated to Xcode 16

* readdded launch resources

* remove wrong ver of core

* remove wrong ver of data

* STASHING WIP

* Removed the data submodules

* WIP...BRCore found but extensions not found

progress

* DID IT DID!!!!!

Compiled!!!

* debugged the tests

* updated the .gitignore

* version bump

* Removed Today Extension

- Removed nothing test

* Added localized strings

update references to strings
- Readded BIP39 list
update rough localization strings
Updated the core library
move references to critical files

* Polished the welcome start view to match Android

* Set user theme mode globally

* update brand images

- removed cruft
- updated dark light mode for logo
- removed extra image

* Implement dark light mode in Start classes

* Fixed tests

* Replaced UIColor and Color with Brainwallet Color theme (#2)

- Added color assets draft

* Epic/gtm color ops fixes (#4)

* Replaced UIColor and Color with Brainwallet Color theme (#2)

- Added color assets draft
- Removed the AnnouncesView (for old email campaign)

Updated all backgroundColor = .white

some dead comments

Updated color scheme :

- PinPadViewC
-LoginViewC

Updated colors of StartFlowPresenter

* Send works

- Transactions are being added but not showing up
- Added draft views
- Fixed lock screen colors
- added new images
add new universal icons
Removed old comments
added moonpay logo
Removed extra TabBarVC
Removed extra TabBar VC
removed the iPad idiom
More color replacements
Removed bitrefill
added timestamp to progress view
removed bad tests
Nice . Able to send
----trasnactions are all missing

* More cleanup

WIP Remvoed NoTabBarVC
-polished views
-Added in UIViews
WIP Hacked in new MainView SwiftUI

ADDING BRAND  new Main View  Storyboards are horrible

Go back to fixing the transactions

DEBUGGING Transactions cells

Debuggiing Send View
fixed sendview controller
sent again
Fixed more colors

* Created FooterView

- moved buttons into HostingCOntroller
Bump and added url
Synchonize dark theme
User pref dark set

* version bump

* Moved more elements in the SwiftUI HeaderView

* chore: ios: Fix smells  comply with App Store (#5)

* 🎥  Epic/gtm refactor core library (#6)

* Found the bug!!!!

Had commented out a bunch of code that was being used
Fixed CustomViewTitle color
fixed-test
version bump
Use brainwallet.co mobile top up
Update WebBuyView.swift
removed comments

* version bump

* Covered the settings colors for light

Just before updating the core
Cruft fixes

* more color fixes

* version bump

* update the core library

* Added Blockheight label

* version bump

* 🧰  Fix/confirm seed words submit (#9)

* Updated core commit

changed Xcode to compile

* Added more tags to debug broken transactions

Added a workaround from Eskimo (iOS 18.4.1 bug)

https://developer.apple.com/forums/thread/777999

Added .ephemeral to the URLSession

Testing to see if iOS 18.3.1 shows the transactions

* version bump

Refactored the submit button
Added some wireframe views
Added dismiss for ConfirmPaperVC

* version bump

- Added test ERROR message
- polish sync label

* Changes the print to debugPrint

* 📽️  Epic/ Add storekit private lib (#7)

* Found the bug!!!!

Had commented out a bunch of code that was being used
Fixed CustomViewTitle color
fixed-test
version bump
Use brainwallet.co mobile top up
Update WebBuyView.swift
removed comments

* version bump

* Added Private StoreKit SwiftPackage

- Cleaned up xcode schemes
-updated to latest core
-updated .gitignore
-Removed unsued code

* Added empty storekit config

Added BrainwalletiOSStoreKite SPM

* updated core

* adjust the sync block height label

* changed to debugPrint

* update gitignore

* 🎥  Epic/add more swift UI views prior to Localizations (#8)

* Send works!

- added rate update
- wireframing the onboarding
- Set basic onboarding
- Added custom dismiss button to ReadyView
- Added more localizations

Fixed the start flow

Core was changed to the wrong commit

Added more assertFailure messages

* version bump

* Ripped Localizations

ALL Broken!!!!!!

* WIP: Added then Localizations Strings catalog

* WIP Added more english text

-Framed in more Views

* update .gitignore

* Re-added the hacked in BuyHostViewController

* version bump

* Added Crashlytics dSym Files per Firebase

https://firebase.google.com/docs/crashlytics/get-started?platform=ios&authuser=0&hl=en#set-up-dsym-uploading

* switched to debugPrint statements

- removed unused swiftformat

* removed commented unused code

* removed unused code

* 🧰  Fix/add localizations (#10)

* Send works!

- added rate update
- wireframing the onboarding
- Set basic onboarding
- Added custom dismiss button to ReadyView
- Added more localizations

Fixed the start flow

Core was changed to the wrong commit

Added more assertFailure messages

* version bump

* Ripped Localizations

ALL Broken!!!!!!

* WIP: Added then Localizations Strings catalog

* WIP Added more english text

-Framed in more Views

* update .gitignore

* Re-added the hacked in BuyHostViewController

* version bump

* Added Crashlytics dSym Files per Firebase

https://firebase.google.com/docs/crashlytics/get-started?platform=ios&authuser=0&hl=en#set-up-dsym-uploading

* Added all AI translated xliff

* Added more Strings(localized tags

* Updated all strings catalogs

Removed old code manageWallet

* version bump

- Removed some exuberant assertFailures

* Current StartView with no Language using the user preferred

* Removed all old Language classes

iOS will auto switch

* Removed the wipe wallet button (#14)

- Added delete data from the settings
- updated service fees
- Added more strings for localization

* 🧰  Fix: Made Scanning work again (#15)

* Polished the UI

* Changed the PIN Length to 4

* Polished the Pin Lock screen

* Polished the Show My Seed words

* Added localizations fixes

* Resorting file structure (Tidying)

Polishes that are general
Resize the image

* Add a animated shape for Send (#17)

* ✨ Worked in the Full SwiftUI with LockScreen (#16)

* Worked in the Full SwiftUI with LockScreen

Polish Start
Fixed PinView leading trailing header
99% SwiftUI  LockScreen
Debugging. the PIN AUTH

* Refactor cruft

- Removed audio files
- polished layout

* polished the localizations

* updated the special shape

Updated package

* per @hassanashraf92 notes (#19)

Refactored opsFees
Added a test

* Refactored to remove strong parent = child references to avoid 🧟‍♂️ (#18)

* ❇️  chore/fetch moonpay countries+ signed buy url (#20)

* WIP: Routed UI changes

Fetch the info and killed 3 tabs

* Refactored in the Buy/Receive for building

Localizable update

Reintegrated Shapes from other merged branch

* Added shapes

removed some cruft
- refactored
- All Tabs work
- Debugged auto select from old business logic
- Renamed Classes BR to BW
- Adding in Rcv
- Switching from Combine to closure for tap QR as launch was firing the RCV modal

* Buzzed out the buy auth through the view stack

* WIP: Add the API Calls

MVP Level layout complete

* Updated the saving of the currencies ud

Success pulling data from API Server
Debug Call for the buy and limits
add more state vars
Heavy refactor to use BuyQuote

* RC adding signedURL

Remove cruft
Added done set amount button

* Successful signedURL!!

* Used AI Generated ViewModelTests

* version and build number

* change file location

* chore: Polish UI (#22)

* version bump

- Update buy and preferred currency across Views to show rates
- Updated localizations
- Polish Segments in Buy view
- Added a MP Logo

* change the symbol

* build bump

* fix: ios: Add wipe button UI polishes (#25)

* UI polishes

build number bump
Small polish of start view
Added wipe button
Adjusted the progress bar color

* resolve package

* Removed the prompt cell as a presentation

- reorged files
- Polished the wipe wallet view

* bump build number

* Added more defensive steps in Wallet Coordinator (#26)

- possible fix
- reshow the rates
- Cover negative amount

More checks

* Fix/localization polishes (#27)

* Added more defensive steps in Wallet Coordinator

- possible fix
- reshow the rates
- Cover negative amount

More checks

* Set the schemes for Russia and Languages

* Added locale debug label

- Deactivate of the Locale button in settings

* Added debug localization label

build bump

* Updated the README

---------

Co-authored-by: Aaron Voisine <voisine@gmail.com>
Co-authored-by: Hassan Ashraf <hassan.ashraf@transflo.com>

* bump

moved epic branch

* Fix/settings UI migration (#38)

* Refactor code to match swiftling

* Saved WIP

* swift lint

* WIP of the new UI

* WIP: Making some progress sliding the settings view contorller

* This change successfully moves the settings view

* Cleaend for claude pre-recommendations

* Working version

* Adjusted the timing

* WIP Adding the settings rows

* Reset structure of the list

Added Footer view

* 20% DONE  in the settings view and its rows

polishing the ui

* WIP Button works but animation is very bad

* WIP

* WIP polish rotation

* polish working Settings

* Refactor to meet swiftlint

* code bump

* Removed Tab

* Resolved issues found in develop branch

* Reconnected the button in the start view

* Got theme working!!!

Checking any cruft

* Polished the Firebase SDK

- Updated the SDK

* remove simple cruft

* 90% Dark theme polished

* Fixed the background in the main vc

Refactor
Removed code smell
Polished dark and light

* build bump

* fixed tabs in config

* build bump

* 🧰  Chore/settings phase 2 (#41)

* Added Lock and Theme working

* Added a closed drawer action for when the the user locks

* Polished SettingsView

* Moved in more expandable row layout

- polished the mainviewcontroller
- polished the settingsview

* updating the currency list

* WIP:  Currency is not setting

* Added Games placeholders

WIP- Blockchain
Fiat Currency
Security

* build bump

* build bump

- linter update
- Polish the send

* Refactored to fully use the settings sections space

* 🎥  Epic:    Settings phase 4 (#47)

* further polish

- set backgrounds
polished footer spacing

* Currency is polished

- Games is polished
- Footer is polished
- Further polish to have list and sections layout

* WIP: Wroking on the Security View

* Completed the security list rows

Need to connect

* Added layout for the blockchain section

* added function for the web views in settings

* added sheets for the urls

* Added basic tests for the settings helper

* Properly calls the share data settings

* PIN reset working

* polished the share data view

* connected the rescan button in settings

* polished the lock action and animation

* Polished the currency action

* polish the currency

* fix test

* Firebase analytics working and polish

* Set the default index

- build bump
- code coverage remove cruft
- fixes the code smell in the rate fetch
- fixed the currency preference

* Removed cruft

* debug the config

* Updated the bundle

upgrade to the high performance runner

* revert runner

* updated ruby version

* polishing the Gemfile

* Update the gemfile

* use scan instead of run_tests

* Udpated the fastfile

---------

Co-authored-by: Aaron Voisine <voisine@gmail.com>
Co-authored-by: Hassan Ashraf <hassan.ashraf@transflo.com>

* 🧰   fix: Removed the thread blocking seen in the lock screen trx. loading (#53)

* Removed the thread blocking seen in the lock screen trx. loading

- Added the further store
- asset no longer used.
- Reordered the fiats

* bump build

* Updated localizations (#54)

* Fix/login view  crash (#55)

* Removed the thread blocking seen in the lock screen trx. loading

- Added the further store
- asset no longer used.
- Reordered the fiats

* bump build

* fix force unwrap in setBalances

bump version

* build version bump

* bump

* updated request

Added request review at launch
..addUserDefaults

* version bump

* 🦾 Chore/migrate ready onboarding (#58)

* polished and activated

- ReadyRestore view
- updated the fonts and colors

* polished the fastfile

* update ruby v3.4.0

* updated the version of Gemfile

* updated the config

* add ruby orb

* explicit invest rbenv

* rm the ubuntu deps

* updated fastlane to 2.228

* clean up fastlane

* broken fastlane ops

* rm workspace

* changed config

* Removed the thread blocking seen in the lock screen trx. loading

- Added the further store
- asset no longer used.
- Reordered the fiats

* bump build

* Add isRestore is added

pollshed the layout

WIP: Seed set and syncing is happening

Need to save PIN

Debugg the confirm isRestore

WIP

Polish factor

WIP: Added shake

- working on seedwords

Added review for frequent users

removed old the unused language references

polished the onboading

WIP Polishing the Restore View

WIP Polishing the Restore View

Changed the seedwords object

Further polish onboarding

Polishing the set passcode

Cut out the back after the confirm the passcode

WIP...adding draggable

WIP Added BucketView

WIP---dragg words

WIP UTType

WIP

WIP Moved all the word views into prove it to manaage the state of the words

WIP dropped and disappearing words

WIP

WIP!!It workd

All function working need to test for real seed

Refactored and cut the code lines

WIP: Reseting the seed words in prove it

* Added TopUp Screen

* WIP: Debugging lock screen

* Working locking , onboarding and unlock

- Reduced the nav stack
- readded Fr
- Added onboarding method in MainViewController
- Still fixing the lock function

* version bump

- adding searchable
- Polished the set word
- Ready to verify the entered Phrase
- Running through all the steps for Ready and Restore

* debugged the config

* Debugging with Windsurf

* remvoed dupe

* readdinstall

* delta rb

* polish config

* changed tne ruby version

* change bundler

* powerwipe

* Updated gemfile

* change the ruby setting in the config

* refactor crash in WalletManager+Auth

using bundle exec fastlane single_unit_test_all
downgrade firebase to 11.12.0
polsih ci config

---------

Co-authored-by: Aaron Voisine <voisine@gmail.com>
Co-authored-by: Hassan Ashraf <hassan.ashraf@transflo.com>

* 🚀[Release v3.7.0] Merge into Main  (#68)

* Initial commit

* refactor: squash history to single commit

* Updated gitignore with new filenames

* Still not finding BRCore

* update config

* removed nettle

* removed the unbound and cleaned

* moved files to br-swift

* WIP import BRCore

* update gitignore

* removed the TE xcscheme

* Updated to Xcode 16

* readdded launch resources

* remove wrong ver of core

* remove wrong ver of data

* STASHING WIP

* Removed the data submodules

* WIP...BRCore found but extensions not found

progress

* DID IT DID!!!!!

Compiled!!!

* debugged the tests

* updated the .gitignore

* version bump

* Removed Today Extension

- Removed nothing test

* Added localized strings

update references to strings
- Readded BIP39 list
update rough localization strings
Updated the core library
move references to critical files

* Polished the welcome start view to match Android

* Set user theme mode globally

* update brand images

- removed cruft
- updated dark light mode for logo
- removed extra image

* Implement dark light mode in Start classes

* Fixed tests

* Replaced UIColor and Color with Brainwallet Color theme (#2)

- Added color assets draft

* Epic/gtm color ops fixes (#4)

* Replaced UIColor and Color with Brainwallet Color theme (#2)

- Added color assets draft
- Removed the AnnouncesView (for old email campaign)

Updated all backgroundColor = .white

some dead comments

Updated color scheme :

- PinPadViewC
-LoginViewC

Updated colors of StartFlowPresenter

* Send works

- Transactions are being added but not showing up
- Added draft views
- Fixed lock screen colors
- added new images
add new universal icons
Removed old comments
added moonpay logo
Removed extra TabBarVC
Removed extra TabBar VC
removed the iPad idiom
More color replacements
Removed bitrefill
added timestamp to progress view
removed bad tests
Nice . Able to send
----trasnactions are all missing

* More cleanup

WIP Remvoed NoTabBarVC
-polished views
-Added in UIViews
WIP Hacked in new MainView SwiftUI

ADDING BRAND  new Main View  Storyboards are horrible

Go back to fixing the transactions

DEBUGGING Transactions cells

Debuggiing Send View
fixed sendview controller
sent again
Fixed more colors

* Created FooterView

- moved buttons into HostingCOntroller
Bump and added url
Synchonize dark theme
User pref dark set

* version bump

* Moved more elements in the SwiftUI HeaderView

* chore: ios: Fix smells  comply with App Store (#5)

* 🎥  Epic/gtm refactor core library (#6)

* Found the bug!!!!

Had commented out a bunch of code that was being used
Fixed CustomViewTitle color
fixed-test
version bump
Use brainwallet.co mobile top up
Update WebBuyView.swift
removed comments

* version bump

* Covered the settings colors for light

Just before updating the core
Cruft fixes

* more color fixes

* version bump

* update the core library

* Added Blockheight label

* version bump

* 🧰  Fix/confirm seed words submit (#9)

* Updated core commit

changed Xcode to compile

* Added more tags to debug broken transactions

Added a workaround from Eskimo (iOS 18.4.1 bug)

https://developer.apple.com/forums/thread/777999

Added .ephemeral to the URLSession

Testing to see if iOS 18.3.1 shows the transactions

* version bump

Refactored the submit button
Added some wireframe views
Added dismiss for ConfirmPaperVC

* version bump

- Added test ERROR message
- polish sync label

* Changes the print to debugPrint

* 📽️  Epic/ Add storekit private lib (#7)

* Found the bug!!!!

Had commented out a bunch of code that was being used
Fixed CustomViewTitle color
fixed-test
version bump
Use brainwallet.co mobile top up
Update WebBuyView.swift
removed comments

* version bump

* Added Private StoreKit SwiftPackage

- Cleaned up xcode schemes
-updated to latest core
-updated .gitignore
-Removed unsued code

* Added empty storekit config

Added BrainwalletiOSStoreKite SPM

* updated core

* adjust the sync block height label

* changed to debugPrint

* update gitignore

* 🎥  Epic/add more swift UI views prior to Localizations (#8)

* Send works!

- added rate update
- wireframing the onboarding
- Set basic onboarding
- Added custom dismiss button to ReadyView
- Added more localizations

Fixed the start flow

Core was changed to the wrong commit

Added more assertFailure messages

* version bump

* Ripped Localizations

ALL Broken!!!!!!

* WIP: Added then Localizations Strings catalog

* WIP Added more english text

-Framed in more Views

* update .gitignore

* Re-added the hacked in BuyHostViewController

* version bump

* Added Crashlytics dSym Files per Firebase

https://firebase.google.com/docs/crashlytics/get-started?platform=ios&authuser=0&hl=en#set-up-dsym-uploading

* switched to debugPrint statements

- removed unused swiftformat

* removed commented unused code

* removed unused code

* 🧰  Fix/add localizations (#10)

* Send works!

- added rate update
- wireframing the onboarding
- Set basic onboarding
- Added custom dismiss button to ReadyView
- Added more localizations

Fixed the start flow

Core was changed to the wrong commit

Added more assertFailure messages

* version bump

* Ripped Localizations

ALL Broken!!!!!!

* WIP: Added then Localizations Strings catalog

* WIP Added more english text

-Framed in more Views

* update .gitignore

* Re-added the hacked in BuyHostViewController

* version bump

* Added Crashlytics dSym Files per Firebase

https://firebase.google.com/docs/crashlytics/get-started?platform=ios&authuser=0&hl=en#set-up-dsym-uploading

* Added all AI translated xliff

* Added more Strings(localized tags

* Updated all strings catalogs

Removed old code manageWallet

* version bump

- Removed some exuberant assertFailures

* Current StartView with no Language using the user preferred

* Removed all old Language classes

iOS will auto switch

* Removed the wipe wallet button (#14)

- Added delete data from the settings
- updated service fees
- Added more strings for localization

* 🧰  Fix: Made Scanning work again (#15)

* Polished the UI

* Changed the PIN Length to 4

* Polished the Pin Lock screen

* Polished the Show My Seed words

* Added localizations fixes

* Resorting file structure (Tidying)

Polishes that are general
Resize the image

* Add a animated shape for Send (#17)

* ✨ Worked in the Full SwiftUI with LockScreen (#16)

* Worked in the Full SwiftUI with LockScreen

Polish Start
Fixed PinView leading trailing header
99% SwiftUI  LockScreen
Debugging. the PIN AUTH

* Refactor cruft

- Removed audio files
- polished layout

* polished the localizations

* updated the special shape

Updated package

* per @hassanashraf92 notes (#19)

Refactored opsFees
Added a test

* Refactored to remove strong parent = child references to avoid 🧟‍♂️ (#18)

* ❇️  chore/fetch moonpay countries+ signed buy url (#20)

* WIP: Routed UI changes

Fetch the info and killed 3 tabs

* Refactored in the Buy/Receive…
* Fix Simulator launch crash: link BWIOSGdx.xcframework device-only

Root cause: BWIOSGdx.xcframework was linked as a required dependency
for every platform via the Frameworks build phase, but its vendored
native libs (gdx-box2d/gdx-freetype/gdx-miniaudio/gdx core, from
libGDX's natives-ios artifacts) are device-only -- byte-identical
(and platform IOS, not IOSSIMULATOR) in both the xcframework's arm64
and arm64-simulator slice folders. The "Flatten+Sign+Relocate Asset
Frameworks" script stripped BWIOSGdx.framework from Simulator builds
to work around this, but that only deleted the file dyld was hard-
required to find, guaranteeing a launch-time crash:

  dyld: Library not loaded: @rpath/BWIOSGdx.framework/BWIOSGdx

Fix: remove BWIOSGdx.xcframework from the automatic Frameworks build
phase and link it explicitly device-only via
"OTHER_LDFLAGS[sdk=iphoneos*]" / "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]"
in both Debug and Release configs. Simulator builds now never
reference BWIOSGdx at the linker level, so there's nothing for dyld
to fail to find -- verified via otool -L (no BWIOSGdx load command)
and an end-to-end install+launch on Simulator with no crash reports.

The Swift-level #if !targetEnvironment(simulator) guards around
bwGameSDK usage in ApplicationController and GameContainerViewController
predate this commit and remain necessary since the game natives still
don't run on Simulator.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* Ignore ASC metadata skill credentials and .p8 keys

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* Fix flaky LockScreenViewUITests: use stable accessibilityIdentifiers

testLockScreenView() was recorded against auto-generated accessibility
labels derived from SF Symbol images (.buttons["moon.stars"],
.buttons["sun.max"], .buttons["qrcode"]). Those labels are unstable:

- The theme button's icon/label flips between "moon.stars" and
  "sun.max" depending on userPrefersDarkMode, so a query for one or
  the other only matches if the button happens to be in that state
  when the test runs.
- iOS renders SF Symbol accessibility labels inconsistently across
  versions (e.g. "moon.stars" vs. the VoiceOver description "Clear
  Night"), which is why Xcode's recorder captured two alternate
  queries for the same element in the first place.

The theme button already had a stable .accessibilityIdentifier("Theme
Preference Button") that the test wasn't using. Added a matching
"QR Code Button" identifier to the receive-address button and updated
the test to key off both instead of the state/OS-dependent labels.

Verified via `xcodebuild build-for-testing` (compiles clean, matches
the real identifiers in LockScreenFooterView.swift). Could not verify
a passing run in this session: xcodebuild test-without-building fails
in this environment with an unrelated debugger-attach error
(DebuggerLLDB.DebuggerVersionStore.StoreError -> SpringBoard denies
launching the xctrunner with wait_for_debugger=1), reproducible even
with the sandbox lifted -- a local CLI/debugger-session issue, not a
code problem. Should pass when run from Xcode directly.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

---------

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
* Fix CircleCI build failure: init and build the bw-gdlib xcframework

build_1841 (run_unit_tests_iPhone16ProMax) failed with:

  error: There is no XCFramework found at
  '/Users/distiller/ios/Private/bw-gdlib/ios/build/robovm/BWIOSGdx.xcframework'.
  (in target 'brainwallet' from project 'brainwallet')

Two things were missing:

1. The submodule init step only initialized Modules/core and
   Private/general-purpose -- Private/bw-gdlib was never checked out,
   so the directory didn't exist at all on the CI box.

2. Even with the submodule checked out, BWIOSGdx.xcframework still
   wouldn't exist: bw-gdlib's ios/build/ is gitignored (same as any
   other Gradle build output), because it's a RoboVM AOT-compiled
   artifact, not something checked into git. It has only ever been
   built manually on developers' Macs -- neither this repo's CI nor
   bw-gdlib's own CircleCI config (which runs on Linux and only does
   ./gradlew :core:test) has ever produced it.

Fix: init Private/bw-gdlib alongside the other submodules, and add a
build step that runs `./gradlew :ios:robovmInstall` (bw-gdlib's Gradle
task that produces build/robovm/BWIOSGdx.xcframework, confirmed via
`./gradlew :ios:tasks --all`) before the fastlane test run, installing
a JDK first if the macOS executor doesn't already have one.

Not yet verified against a live CircleCI run (no local runner
available) -- please confirm the next push on this branch turns the
job green, particularly the RoboVM build step's timing and the
openjdk@17 Homebrew install path on the macos.m1.medium.gen1 executor.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* Avoid needing BWIOSGdx.xcframework in CI at all

The previous commit tried to fix CI by building the framework there
(git submodule init + `./gradlew :ios:robovmInstall`), but that failed
too: bw-gdlib has its own nested submodule (android-build-logic, for
a Gradle version catalog) that a non-recursive `submodule update
--init Private/bw-gdlib` doesn't fetch, so Gradle failed on a missing
libs.versions.toml.

Chasing that down further, building the framework in CI was solving
the wrong problem. Simulator builds never need BWIOSGdx at all --
the game is entirely #if !targetEnvironment(simulator)-guarded in
Swift -- but Xcode's Frameworks and Embed Frameworks build phases
still referenced the xcframework unconditionally for every platform,
so Xcode tried to resolve/embed the file regardless and errored with
"There is no XCFramework found" the moment it didn't exist, before our
existing simulator-only linker scoping ([sdk=iphoneos*]) ever mattered.

Fix:
- Remove BWIOSGdx.xcframework from the Embed Frameworks build phase
  too (it was already removed from the Frameworks/link phase in the
  simulator-crash fix). Xcode now never touches the file for any
  platform.
- Move the embedding Xcode used to do automatically into the
  "Flatten+Sign+Relocate Asset Frameworks" script instead, gated the
  same way as the rest of that script: skip entirely on Simulator,
  copy+sign+flatten it for device builds (erroring with a clear
  message if the file's missing there, instead of Xcode's opaque one).
- Revert the CircleCI submodule-init and Gradle build step from the
  previous commit -- no longer needed since Simulator/CI builds don't
  touch BWIOSGdx at all now.

Verified locally: moved Private/bw-gdlib/ios/build/robovm/BWIOSGdx.xcframework
out of the way entirely (reproducing a fresh CI checkout) and did a
clean Simulator build -- BUILD SUCCEEDED, app installs and launches
normally. Restored the framework afterward and confirmed device-slice
FRAMEWORK_SEARCH_PATHS/embedding logic is unchanged for real device
builds.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* Fix Xcode Cloud ci_post_clone.sh: actually write the secret files

ci_post_clone.sh wrote the literal strings "GOOGLE_SERVICES_PLIST",
"REMOTE_CONFIG_DEFAULTS", and "DEBUG_SERVICE_DATA" into their
respective files -- missing the '$' to dereference the environment
variables entirely, so GoogleService-Info.plist etc. never contained
real content on any Xcode Cloud run. Even with '$' added it would
still be wrong: these vars are base64-encoded in Xcode Cloud's
environment variable settings, same as their proven-working CircleCI
counterparts in .circleci/config.yml's "Setup environment files" step,
and this script never decoded them.

Also: Brainwallet-StoreKit-v1.storekit was never written for Xcode
Cloud at all, unlike CircleCI which creates it from
BRAINWALLET_IOS_STOREKIT_V1_0_FILE alongside the other three files.

Fix: dereference + base64-decode all four env vars into
PreLaunchResources, matching CircleCI's approach, and fail fast with
a clear message if GoogleService-Info.plist doesn't decode to a valid
plist (via PlistBuddy) instead of silently shipping garbage.

Verified via a dry run with real base64-encoded fake values: decoded
content matches exactly, and the PlistBuddy validation passes.

Not yet verified against a live Xcode Cloud run -- no CI report was
provided for this one, this was found via code review (comparing
against CircleCI's already-proven equivalent step). If Xcode Cloud
also runs an Archive/TestFlight workflow (as opposed to only the
brainwalletUITests scheme this script pre-resolves packages for), it
will still need Private/bw-gdlib's BWIOSGdx.xcframework built via the
existing "Build RoboVM" Xcode build phase (runOnlyForDeploymentPostprocessing,
so archive-only) -- worth checking submodule access is granted to
bw-gdlib in Xcode Cloud's source control settings if that workflow
exists and fails.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* Fail fast on bad CI secrets instead of a cryptic xcodebuild plist error

Xcode Cloud build 431 (brainwalletUnitTests build-for-testing) failed
90+ seconds into the actual xcodebuild step with:

  error: unable to read input file as a property list: The operation
  couldn't be completed. (SWBUtil.PropertyListConversionError error 2.)
  (in target 'brainwallet' from project 'brainwallet')

during the CopyPlistFile resource-processing step for service-data.plist.
Traced it to the root cause: DEBUG_SERVICE_DATA's value in Xcode Cloud's
environment variable settings (App Store Connect) doesn't base64-decode
to a valid plist. (ci_post_clone.sh's base64 decoding itself is working
correctly -- confirmed from this same build's ci_post_clone.log:
GoogleService-Info.plist and remote-config-defaults.plist, decoded by
the identical code path, copied without error.) That's a secret
misconfigured on Apple's side, outside this repo -- flagging for
whoever manages Xcode Cloud's App Store Connect settings to fix.

What this commit does fix: neither CI script actually verified the
other three generated files were valid before handing them to
xcodebuild, so a bad secret's failure mode was a confusing build-system
error far removed from its actual cause. Extended validation (already
added for GoogleService-Info.plist after the ci_post_clone.sh env-var
bug) to remote-config-defaults.plist and service-data.plist (PlistBuddy)
and Brainwallet-StoreKit-v1.storekit (python3 -m json.tool -- it's JSON,
not a plist, so plutil -lint rejects it outright regardless of validity).
Applied to both ci_scripts/ci_post_clone.sh and .circleci/config.yml's
"Setup environment files" step, since both decode the same four env
vars and either could hit the same class of bug.

Verified via dry runs with real base64-encoded fixtures: all 4 valid ->
clean pass; DEBUG_SERVICE_DATA broken (matching build 431's actual
failure) -> fails immediately with the exact var/file named, instead of
xcodebuild's opaque error later.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* Fix locale-dependent test failure in testISO8601DateFormatterFormat

Surfaced on Xcode Cloud build #436, the first build to actually get
brainwalletUnitTests compiling and running there:

  [TEST_FAILURE] NewReceiveTests.swift:192: XCTAssertTrue failed

The test asserted the formatted date string contains the English
month abbreviation "jun", but configured the formatter with
Locale.current -- Xcode Cloud's build agent's default locale doesn't
format months the same way as a developer's en_US Mac, so the
assertion failed for a reason that has nothing to do with the date
formatting logic under test. Fixed by using a deterministic
en_US_POSIX locale, standard practice for locale-independent
date-format tests.

Verified locally: testISO8601DateFormatterFormat passed (0.413s) via
xcodebuild test-without-building -only-testing.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* Pin timeZone too -- the locale fix alone wasn't enough

Xcode Cloud build #438 (on af4a2f4, the locale fix) still failed the
exact same assertion:

  [TEST_FAILURE] NewReceiveTests.swift:197: XCTAssertTrue failed
  XCTAssertTrue(formattedString.contains("jun"))

en_US_POSIX fixed the locale half of the problem but not the other
half: formatter.timeZone was never pinned, so it inherited the
executing machine's system time zone. The test date (1717200000) is
June 1 00:00:00 UTC, which is still May 31 in any zone west of UTC:

  TZ=America/Los_Angeles date -r 1717200000  ->  Fri May 31 17:00:00 PDT 2024
  TZ=America/New_York date -r 1717200000     ->  Fri May 31 20:00:00 EDT 2024

My Mac happens to be on BST (UTC+1), where that instant is still
"01 Jun" -- which is exactly why this passed locally both times but
kept failing on Xcode Cloud's build agent, whose system time zone is
apparently west of UTC. Pinned formatter.timeZone to UTC, matching
what the test's own comment already claims the date represents.

Verified locally: testISO8601DateFormatterFormat passed (0.083s).

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* Stop printing decoded GoogleService-Info.plist content to CI logs

Flagged directly: does anything in this branch leak secrets, given the
repo is public? ci_post_clone.sh itself is clean -- confirmed it only
ever references env var *names*, never literal values, the four
generated files are all gitignored, and none are currently tracked.

But .circleci/config.yml had a pre-existing (not introduced by this
branch) `head -10 GoogleService-Info.plist` right after decoding it,
intended as a "safe" debug dump ("avoid showing sensitive data" per
its own comment) but not actually safe: this repo is public, and
CircleCI serves build logs for public GitHub repos without requiring
a CircleCI login by default, so the first 10 lines of a small XML
plist (API_KEY, GOOGLE_APP_ID, etc. included) were one real CircleCI
run away from being publicly readable.

Replaced with a comment pointing at check_plist (added earlier in
this branch), which already validates the decoded content is a real
plist via PlistBuddy without ever printing it -- the correct way to
verify this.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* Fix the same GoogleService-Info.plist log-leak in the other 2 CircleCI configs

0a383bf fixed `head -10 GoogleService-Info.plist` in .circleci/config.yml
(printing decoded secret content into build logs of a public repo, whose
CircleCI logs are viewable without a login by default). Asked to check
the rest of the repo for similar leaks: the exact same block was
copy-pasted into build-uitest-config.yml and daily-develop-config.yml
too, unfixed.

Applied the identical fix to both: content-blind plist validation via
PlistBuddy (check_plist) instead of printing decoded lines. Also added
the StoreKit JSON validation to daily-develop-config.yml, which writes
that file but never validated it (build-uitest-config.yml doesn't
decode a StoreKit file at all, so it doesn't need that check).

Everything else checked clean: no .p8/.storekit/provisioning
profiles/real GoogleService-Info.plist ever committed anywhere in this
repo's current tree; GitHub Actions workflows use native secrets.X
(auto-redacted by GitHub); Fastfile doesn't touch any of these files.

Separately (not fixed here, flagged to the user directly): a real
service-data.plist with actual wallet-ops/AppsFlyer data was committed
in this repo's early history (033e2b4, 6575eb1) and is still reachable
from origin/develop and ~100 branches -- a git-history exposure, not a
CI-log one, and a materially different fix (rotation + possible history
rewrite) that needs the user's explicit direction before anyone touches it.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

---------

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
)

Pulls in core's fix for Firebase Crashlytics issue
9f86d0dd9962b0efc34252c4c41b2659 (gruntsoftware/core#19): EXC_BAD_ACCESS
at address 0x0 in _peerThreadRoutine. pthread_cleanup_pop(1) invoked
ctx->threadCleanup unconditionally, unlike every other optional
callback in the same function, which are null-checked first -- if
threadCleanup was ever unexpectedly NULL, that's a call through a null
function pointer, exactly matching this crash's signature. Now guarded
the same way, falling back to the existing no-op default.

Matches the ef1bda5 precedent: root-cause and fix land in
gruntsoftware/core via its own fix/crashlytics-<hash> branch and PR
(gruntsoftware/core#19, merged, verified there with `make test` --
zero new failures vs. unpatched main), this commit just bumps the
pinned submodule commit to pull it in.

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
… BWIOSGdx link (#156)

* Update project

* update game to v1.6.7(8)

* update the v1.6.8

* Fix Simulator crash: remove BWIOSGdx.xcframework re-added to Frameworks/Embed

014f068 ("update the v1.6.8") re-added BWIOSGdx.xcframework to the
unconditional Frameworks and Embed Frameworks build phases -- almost
certainly via Xcode's own "add framework" UI while troubleshooting a
device build, since that's Xcode's default behavior for any framework
added through its interface.

This undoes ios#154's device-only-scoped linking fix (OTHER_LDFLAGS/
FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*], deliberately NOT using the
Frameworks/Embed Frameworks phases, since phase membership doesn't
respect SDK qualifiers and applies to every platform unconditionally).
Harmless on device (just a redundant second link path alongside the
scoped one), but reintroduces the exact Simulator crash that fix
eliminated: Simulator tries to link/embed BWIOSGdx.xcframework, whose
simulator slice has device-only vendored native libs
(gdx-box2d/gdx-freetype/gdx-miniaudio/gdx core -- byte-identical to
the device slice, confirmed earlier this session).

Verified: reproduced against a clean `develop` in an isolated
worktree first (fresh clone, fresh submodules, no local changes) to
confirm this wasn't actually a develop regression -- builds, installs,
and launches fine there, proving the bug was local-only. Then applied
the same fix here: BUILD SUCCEEDED, installs, launches, and stays
running on Simulator.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* bumped

---------

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Removes code and resources confirmed unused across the ios repo
(submodules excluded), validated with a full clean build + test
build after every batch:

- Whole orphaned directories not referenced by the Xcode project:
  brainwallet/Launch Resources/ (stale duplicate of PreLaunchResources/)
  and brainwalletTests/ (leftover from a retired test target).
- 55 orphaned .swift files never wired into any build target, mostly
  stale duplicates left behind by the SwiftUI rewrite (e.g. root-level
  ApplicationController.swift, BuyViewModel.swift,
  TabBarViewController.swift), plus a fully commented-out
  UtilityTests.swift.
- Unused code inside otherwise-live files: dead Redux actions in
  Actions.swift (and their now-orphaned clone helpers), an unused
  GradientView/GradientDrawable gradient-drawing path,
  PaymentProtocolACK/PaymentProtocolPayment, several unused SwiftUI
  view modifiers/structs, and a few commented-out dead-code blocks.
- Dead resources: 3 unused product images (amazon_logo, je_logo,
  visa_logo), 3 sound files bundled but never played (clicksound.wav,
  clicksound.aiff, clickseedword.mp3), and a stray committed
  testScript Mach-O binary.

project.pbxproj updated to match everywhere a compiled file or
resource reference was removed.

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Checkpoint build covering everything merged into develop over the
last 48 hours (2026-08-13 through 2026-08-14):

- #153 Fix Simulator launch crash + flaky LockScreenViewUITests:
  link BWIOSGdx.xcframework device-only (via OTHER_LDFLAGS/
  FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*] instead of the unconditional
  Frameworks build phase) so Simulator builds never require its
  device-only vendored natives; also stabilized a flaky lock-screen
  UI test that depended on locale/theme-dependent SF Symbol labels.

- #154 Fix CircleCI + Xcode Cloud build failures: stopped trying to
  build BWIOSGdx.xcframework in CI (Simulator never needs it) and
  moved its embedding into the existing Flatten+Sign+Relocate script;
  fixed ci_post_clone.sh to actually dereference and base64-decode
  its secret env vars into GoogleService-Info.plist /
  remote-config-defaults.plist / service-data.plist /
  Brainwallet-StoreKit-v1.storekit; added fail-fast validation for
  all four generated files across both CI providers; fixed a
  locale- and timezone-dependent date-formatter test failure; and
  removed a GoogleService-Info.plist content dump from three CircleCI
  configs that could have leaked API keys in this public repo's logs.

- #155 Bump Modules/core: pulls in a fix for a Crashlytics-reported
  EXC_BAD_ACCESS in _peerThreadRoutine (null-checks threadCleanup
  before invoking it, matching every other optional callback in the
  same function).

- #156 Bump bw-gdlib to v1.6.8, fix Simulator crash regression:
  the game-SDK bump's Xcode-UI framework changes re-added
  BWIOSGdx.xcframework to the unconditional Frameworks/Embed phases,
  regressing #153's Simulator fix; removed it from those phases again.

- #157 chore: remove defunct code, resources, and dead files: 328
  files / ~12.5k lines removed across the ios repo (orphaned Launch
  Resources/ and brainwalletTests/ directories, 55 files never wired
  into any build target, dead code cascades inside otherwise-live
  files, and unused images/sounds), validated with a full clean build
  and test-build after every batch.

This commit itself: build-number bump only, plus Xcode's own
formatting pass over Localizable.xcstrings (key/value spacing) picked
up incidentally when the project was last opened.

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
…o-98%-sync (#161)

* fix: sync-duration analytics event never fired; log foreground time-to-98%-sync

user_did_complete_sync required walletState.syncProgress >= 0.999 AND
walletState.syncState == .syncing in the same dispatched state, but
WalletCoordinator.onSyncStop() invalidates the progress timer and
dispatches setSyncingState(.success) as a separate store action from
the final setProgress. By the time the last block-height update
landed, syncState had usually already flipped to .success, so the
isSyncing gate skipped the check entirely -- the event essentially
never fired.

Goal is a foreground-sync-duration average, to be able to promote the
shortest sync time to users -- so this measures accumulated active
syncing time while the app was in the foreground, not wall-clock time
from wallet creation to completion (which would include however long
the app sat backgrounded/closed mid-sync, and isn't a fair "how fast
is our sync" number).

- WalletCoordinator now owns the metric, since it's the actual owner
  of the sync start/stop lifecycle (not a Redux subscription racing
  against it). Tracks active-foreground-sync segments: a segment opens
  on onSyncStart or didBecomeActiveNotification (only if still mid-sync),
  and closes on onSyncStop or willResignActiveNotification -- so the
  ~30s grace period the peer manager can keep running into the
  background (until the background task's expiration handler
  disconnects it) isn't counted as foreground time either. Elapsed
  segments accumulate into UserDefaults.foregroundSyncDurationSeconds.
  Once block-height progress first crosses kSyncDurationThreshold
  (98%), logs the accumulated total in seconds as a Firebase parameter:
  user_did_complete_sync now sends sync_duration_seconds instead of
  parameters: nil.
- Both foregroundSyncDurationSeconds and the one-shot
  hasLoggedInitialSyncDuration flag are persisted (a sync can span
  multiple app sessions before reaching 98%), and both get wiped for
  free by the existing wipeWallet() (removePersistentDomain), so a
  fresh wallet gets a fresh measurement window with no extra cleanup.
- Outlier cap: durations past kMaxSyncDurationSeconds (24h) are
  discarded rather than logged. Matters less now that background time
  no longer leaks into the number in the first place, but kept as a
  backstop against clock skew / a pathologically bad connection.
- NewMainViewModel.didRestoreOldBrainwallet(): dispatch
  WalletChange.setWalletCreationDate(Date()), matching
  generateNewWallet() -- Restore never set this, so walletState.creationDate
  (persisted into WalletInfo via KVStoreCoordinator) stayed at
  Date.zeroValue() for every restored wallet. Independent fix, kept
  even though the duration metric no longer depends on creationDate.

Verified via xcodebuild build and build-for-testing (both succeed).

Still needed: register sync_duration_seconds as a Custom Definition
in the Firebase console (Analytics > Custom definitions) to use it in
Reporting -- that's a console-side step, not code. p50/p90 aren't
something the client can compute (each wallet only ever sends one
value); they require the BigQuery export linked and a percentile query
over sync_duration_seconds, not a code change.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* fix: FallinScene/WelcomeFallinScene leak forever via unweakified recursive delay (#162)

FallinScene.makeDot() reschedules itself via delay(2.0) { ... self.makeDot() ... }
with no [weak self], no cancellation, and no termination condition. Every
call -- including the automatic one from didMove(to:) -- starts a GCD
timer chain on the main queue that fires every ~2s for the rest of the
process's life; the closure's strong self-capture means the scene can
never be deallocated once it starts. This isn't test-only: FallinScene
is live via FallinMojiDemoView -> GameHubBentoView, so every time a
user opens the Game Hub bento, this leaks a scene that recurses forever
in the background.

Root-caused BrainwalletUnitTests failure:
  FallinSceneTests.testMakeDot_CreatesLabelNode()
  Asynchronous wait failed: Exceeded timeout of 1 seconds, with
  unfulfilled expectations: "Wait for node creation"
scene.makeDot() itself is synchronous (addChild happens immediately);
the wait is just scaffolding. The 6+ tests in FallinSceneTests each
call makeDot(), leaving behind permanently-recursing orphaned scenes
that pile up competing for the main run loop across the suite -- enough
backlog to make a trivial 0.1s asyncAfter miss a 1s timeout.

Fix: [weak self] + guard in the recursive closure, so an orphaned scene
can actually be deallocated once nothing else references it, stopping
the chain.

WelcomeFallinScene.makeSprites() has the same pattern (delay(1.0) { ...
self.makeSprites() ... }, no [weak self]). It does self-terminate (the
30s countdown reaching 0 breaks the chain), but without weakifying, a
user backing out of the view mid-game keeps it recursing and mutating
@binding var counter/countdown/didStartGame for up to 30s after the
view is gone. Fixed the same way, plus the same missing [weak self] in
touchesBegan's one-shot delay(0.1) (smaller window, same pattern).

Verified: ran FallinSceneTests directly on iPhone 16 Pro (iOS 18.5) --
all 8 tests pass, including testMakeDot_CreatesLabelNode() at 0.107s.
xcodebuild build and build-for-testing both succeed.

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>

---------

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Bumps Private/bw-gdlib from ab90257 to 68b03cb:
- Add QR privacy hide/show toggle to GameEndView
- Bump fallinmoji version to 1.6.9 (code 10)
- Update README release notes and badge for v1.6.9

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <noreply@anthropic.com>
Co-authored-by: kcw-grunt <kerry@grunt.ltd>
* Update project.pbxproj

* chore: bump build to 2602307

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

---------

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
* chore: remove CircleCI, rely on Xcode Cloud for CI

CircleCI's macOS executor costs had gotten too high. Xcode Cloud
(ci_scripts/) already runs the build/test pipeline, so it's now the
sole CI for this repo.

- Delete .circleci/ (per-push unit tests, daily-develop maintenance
  job, and UI-test/weekly-maintenance job)
- Remove setup_circle_ci from fastlane/Fastfile's before_all
- Move the Linux-only i18n translation-coverage check
  (scripts/test_i18n_coverage.py) to a new GitHub Actions workflow
  (.github/workflows/i18n-coverage.yml) since it has no Xcode Cloud
  equivalent
- Drop the CircleCI status badge and the CircleCI-updated Gist
  tests-badge from README; update the Testing section to reference
  Xcode Cloud + the new i18n workflow
- Clean up stale .circleci references in ci_scripts/ci_post_clone.sh
  and .github/workflows/pr-summary.yml

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* remove duplicate bwiosgdx

* bumped code

---------

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
* fix: clear easy Swift compiler warnings

Mechanical, behavior-preserving cleanup of the low-risk warnings from a
full warnings review: unused GeometryReader width/height locals, a dead
if-let block, unnecessary try? on a non-throwing call, a non-exhaustive
switch on UIGestureRecognizer.State, deprecated Data(bytes:) inits, a
write-only dead variable, and refactoring WalletCoordinator's manual
weak-var-capture pattern to the idiomatic [weak self] closure capture.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* fix: replace deprecated UIApplication.windows with currentKeyWindow helper

UIApplication.windows was deprecated in iOS 15 in favor of going through
UIWindowScene. Adds a single UIApplication.currentKeyWindow extension
(via UIWindowScene.keyWindow across connectedScenes) and swaps in the
three call sites that were each independently doing the old
`.windows.filter { $0.isKeyWindow }.first` dance -- ModalPresenter.swift,
ModalPresenter+Extension.swift, and ModalTransitionDelegate.swift.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* fix: replace deprecated SwiftUI .animation(_:) with value-scoped variant

.animation(_:) (no value:) implicitly animates any state change to the
view, which is why it was deprecated in iOS 15. Scope it to the specific
binding actually driving the change (shouldExpandBlockchain) instead.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* fix: migrate SCNetworkReachability to NWPathMonitor

SCNetworkReachabilityCreateWithName/SetCallback/SetDispatchQueue/GetFlags
were deprecated in iOS 17.4. Rewrites ReachabilityMonitor on top of
Network.framework's NWPathMonitor, keeping its existing public surface
(didChange closure, isReachable) so its three call sites (WalletCoordinator,
ModalPresenter, ApplicationController) are unaffected. Also drops the
manual Unmanaged/UnsafeMutableRawPointer C-callback trampoline the old
implementation needed.

WalletManager.networkIsReachable() -- called synchronously from the C
peer-manager's networkIsReachable callback, so it can't become async --
now owns a long-lived ReachabilityMonitor and just reads its isReachable
property instead of the deprecated SCNetworkReachabilityCreateWithAddress/
GetFlags pair.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* fix: scope dangling raw-pointer usage in BRAddress and seed generation

UnsafeMutableRawPointer(mutating: &x) / UnsafeRawPointer([x]) are only
valid for the duration of the single call they're constructed in;
chaining .assumingMemoryBound(...) and using the result afterward (or,
worse, across several later calls) uses the pointer outside that
guaranteed scope -- undefined behavior the compiler now flags as
"results in a dangling pointer".

BRAddressExtension.swift: every init/accessor touching the address's raw
`s` buffer (init?(string:), init?(scriptPubKey:), init?(scriptSig:),
scriptPubKey, hash160, description) now does its C-interop call from
inside a withUnsafeBytes/withUnsafeMutableBytes(of:) closure instead of
a pointer built ahead of time.

WalletManager+Auth.swift: setRandomSeedPhrase()'s BIP39 entropy pointer
(entropyRef) was reused across SecRandomCopyBytes and two BRBIP39Encode
calls spanning several lines -- the most serious instance of this
pattern, since it's seed-entropy generation. Wrapped all three uses
inside a single withUnsafeMutableBytes(of: &entropy) closure.

Verified via BRAddressTests, WalletCreationTests, and
WalletAuthenticationTests (all pass) that behavior is unchanged.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* test: add unit tests for BRAddressExtension and WalletManager+Auth

BRAddressExtensionTests: self-contained, deterministic coverage of
BRAddress's init(string:)/init(scriptPubKey:)/scriptPubKey/hash160/
description/Equatable/Hashable, using a hand-built P2PKH scriptPubKey
fixture rather than depending on wallet setup or the keychain.

WalletManagerAuthTests: covers setSeedPhrase, the seedPhrase(pin:) round
trip, changePin, pinLength, and wipeWallet -- business logic not already
exercised by WalletAuthenticationTests (pin lock-out) or WalletCreationTests
(random seed-phrase generation).

Both exercise the exact code paths touched by the preceding dangling-
pointer and SCNetworkReachability fixes, so they'll catch regressions
there going forward.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* fix: migrate withUnsafeBytes/withUnsafeMutableBytes off deprecated typed-pointer overloads

Data.withUnsafeBytes/withUnsafeMutableBytes closures typed with a
concrete pointer type (e.g. (UnsafePointer<UInt8>) -> R) resolve to the
deprecated overload; the replacement overload's closure parameter is
UnsafeRawBufferPointer/UnsafeMutableRawBufferPointer. Migrated every
site across Extensions.swift (md5, base58 encode/decode, sha1/sha256,
uInt256, the uInt8/32/64(atOffset:) accessors, compactSign, genNonce,
the masterPubKey getter, BRKey.publicKey), BRKeyExtension.swift
(privKey/bip38Key), BRReplicatedKVStore.swift's genNonce duplicate, and
WalletManager+Auth.swift (creationTime load, BIP39 encode, apiAuthKey,
the generic Int64 keychainItem loader).

Where the underlying C function takes void* (BRMD5, BRSHA1/256,
BRKeyCompactSign, BRKeyPubKey) the fix is just .baseAddress; where it
takes a typed pointer (BRBase58Encode/Decode's char*/uint8_t*,
BRKeyPrivKey/BRKeyBIP38Key's char*) it's
.baseAddress?.assumingMemoryBound(to:); reinterpreting raw bytes as a
value (uInt256, the offset accessors, the Int64 keychain case) uses
.load(as:).

BRMasterPubKey.pubKey is a 33-byte C-array-as-tuple; calling the global
withUnsafeMutableBytes(of:) on that tuple projection crashed the type
checker ("failed to produce diagnostic for expression") instead of
compiling, so the masterPubKey getter instead uses
withUnsafeMutablePointer(to:) + withMemoryRebound(to: UInt8.self).

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* test: add ExtensionsCryptoTests for the Extensions.swift crypto/encoding helpers

md5, sha1/sha256, base58 encode/decode, uInt256, the uInt8/32/64(atOffset:)
accessors, and the BRMasterPubKey<->Data round trip had no test coverage
at all. Added known-vector and round-trip tests for each, verified
against the withUnsafeBytes/withUnsafeMutableBytes migration in the
preceding commit -- a mistake in that pointer plumbing would show up
here as a wrong hash rather than just a cleared warning.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* fix: clear remaining deprecation warnings, badge count, and mock test scaffolding

- applicationIconBadgeNumber (deprecated iOS 17): WalletCoordinator now tracks
  its own pending badge count (UserDefaults.pendingNotificationBadgeCount,
  reset alongside AppDelegate's existing setBadgeCount(0) calls) since
  UNUserNotificationCenter.setBadgeCount(_:) has no matching getter.
- FakeAuthenticator/testPublicKeyEncoding (BWAPIClientTests.swift): migrated
  the remaining withUnsafeBytes/withUnsafeMutableBytes calls off the
  deprecated typed-pointer overloads; apiAuthKey's BRKeyPrivKey call also
  had the pointer-escapes-the-closure pattern fixed (matches the
  BRKey.publicKey fix from earlier in this cleanup).
- MockURLSessionDataTask / MockURLSession: restated `@unchecked Sendable`
  (required under Swift 6 concurrency checking when subclassing a Sendable
  Foundation type) with comments explaining why each is safe.
- Removed MockURLSession.swift and MockURLSessionDataTask.swift entirely --
  neither was ever actually instantiated (mockURLSession stayed nil), so
  the URLSessionDataTask() deprecation inside them was dead code; deleting
  it is the only real fix, since wrapping the call in a helper only
  relocates the same warning rather than removing it (verified).
- Replaced the two remaining bare URLSessionDataTask() calls in
  BWAPIClientTests.swift's redirect/challenge tests with the real
  URLSession.dataTask(with:) factory method.

That last change gave testURLSession_Redirect_ToDifferentHost_DoesNotFollow
a real task for the first time, which exposed it as a false positive: it
only passed because a never-started bare task has a nil currentRequest,
not because the code under test actually blocked the redirect.
BWAPIClient.urlSession(_:task:willPerformHTTPRedirection:newRequest:...)
only checked the redirect's *origin* host against api.grunt.ltd, never the
*destination* -- so a redirect issued by our own API pointing anywhere
else would have been followed. Fixed both:
- BWAPIClient.swift now also requires the redirect's destination host/scheme
  to match our own API before following it.
- Fixed the existing test to genuinely exercise that check, and added
  testURLSession_Redirect_FromDifferentHost_DoesNotFollow (untrusted
  origin) and testURLSession_Redirect_SameHost_Follows (positive case)
  alongside it.

Also included: SignupAskViewTests' two branch-simplification fixes,
MockAuthenticationChallengeSender split into its own file, and removing
the long-dead "Run Script for CircleCI SPM Caching" build phase left over
from the earlier CircleCI removal.

Verified with a full clean build (0 errors, 0 warnings in every touched
file) and the full BWAPIClientTests/SignupAskViewTests suites (33 tests).

Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>
Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>

---------

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
…g the way (#175)

* fix: remove dead code found while auditing warnings (UIView frame swizzle, MessageUIPresenter)

UIView+FrameChangeBlocking.swift: swizzled UIView's frame setter app-wide
at launch, gating writes on a per-instance isFrameChangeBlocked flag --
but nothing anywhere ever set that flag to true, so the swizzle had zero
functional effect; every frame write just paid for an extra method-call
hop through requestSetFrame(_:) for nothing. Its "equivalent of
dispatch_once" comment was also stale/inaccurate: a bare static func has
no actual once-guard, so a second call to swizzleSetFrame() would have
silently un-swizzled it via method_exchangeImplementations.

MessageUIPresenter: instantiated once in ModalPresenter (messagePresenter),
but that property was never referenced again anywhere -- none of
presentMailCompose/presentFeedbackCompose/presentSupportCompose were ever
called.

Removed both entirely, including their pbxproj file/build-phase entries.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* fix: stop performRequestWithRetry from recursing unconditionally

attemptRequest() called itself immediately after firing its URLSession
data task, outside the retry-on-failure branch -- so every call recursed
synchronously before any network response could return, regardless of
whether the request actually needed retrying. This was flagged during an
earlier warnings review (the compiler's "function call causes an infinite
recursion" diagnostic on this same function) as a critical bug distinct
from the review's warning cleanup; fixing it here.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* fix: small Swift-safety cleanups in Legacy_BW_BRClasses

- BRMasterKeyExtension.swift: mark the retroactive Equatable conformance
  on BRMasterPubKey (an imported BRCore type) with @retroactive, per the
  compiler warning that this won't behave correctly if BRCore itself adds
  the conformance in the future.
- BRReplicatedKVStore.swift: replace a force-cast (as!) with a safe
  optional cast (as?) when handing a caught error to completionHandler.
- BRTxInputExtension.swift: line-wrap reformatting only, no behavior change.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* fix: scope dangling pointers and migrate deprecated Security APIs in PaymentProtocolRequest

certs/digest: UnsafeMutablePointer(mutating:) on a Swift array/let escaped
its guaranteed-valid scope (same pattern fixed elsewhere this cleanup);
now scoped via withUnsafeMutableBufferPointer.

isValid()'s certificate-trust and signature-verification flow:
- SecTrustEvaluate + SecTrustCopyProperties (manual error-string
  extraction from a loosely-typed properties array) -> SecTrustEvaluateWithError,
  which returns the trust decision and a descriptive CFError in one call.
- SecTrustCopyPublicKey -> SecTrustCopyKey (direct rename).
- SecKeyRawVerify(_, .PKCS1SHA256/.PKCS1SHA1, ...) -> SecKeyVerifySignature(_,
  .rsaSignatureDigestPKCS1v15SHA256/SHA1, ...), the documented replacement
  for verifying a PKCS1v15 signature over an already-hashed digest.

The errSecUnimplemented-sentinel trick for distinguishing "unsupported
pkiType" from "verification failed" is now an explicit pkiType check
instead of relying on an OSStatus that was never reassigned.

Verified via full clean build (0 errors/warnings in this file) and the
existing PaymentRequestTests suite. isValid()'s trust/signature path
itself has no direct automated coverage (pre-existing gap, not
introduced here) -- building real fixtures for it would need a
self-signed cert and BRTxOutput construction, worth its own task.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

* fix: migrate userAccount keychain storage off deprecated NSKeyedArchiver APIs

The generic keychainItem<T>/setKeychainItem<T> pair's [AnyHashable: Any]
case (backing WalletManager.userAccount) used the deprecated
NSKeyedArchiver.archivedData(withRootObject:) / NSKeyedUnarchiver.unarchiveObject(with:).
Both functions already throw, so:
- write: archivedData(withRootObject:requiringSecureCoding: true)
- read: unarchivedObject(ofClasses:from:) with an explicit allowlist of
  the plist-compatible classes a userAccount blob can actually contain
  (NSDictionary/NSArray/NSString/NSNumber/NSDate/NSData/NSNull)

userAccount had no test coverage at all; added a round-trip test and a
nil-before-set test to WalletManagerAuthTests.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

---------

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
- Header now shows an explicit close button alongside centered title
- QR/address block shows the full address (no truncation), centered
  "COPY NEW ADDRESS" affordance with a bordered copy icon
- Currency wheel picker shows more surrounding rows, has its default
  row background stripped (UIPickerView+Extension.swift), and brackets
  the selected row with hairlines
- Preset amount segmented control replaced with bordered pill chips
  (min / 10x / max / Custom), Custom reveals inline amount entry
- Buy button unified into a single lavender rounded rect with the
  MoonPay attribution folded in, relabeled BUY LTC
- All content now sits in a single BrainwalletColor.surface container
  sized 90% width / 60%[->75%] height of the sheet
- Sheet itself now presented as translucent (presentationBackground +
  a dialed-down VariableBlurView, since ultraThinMaterial + opacity
  only fades the blur rather than thinning it)

Co-authored-by: kcw-grunt <mrkerrywashington@icloud.com>
Co-authored-by: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Removes every entry whose extractionState is "stale" (Xcode's own
marker meaning it found no source reference during the last build),
plus two more (GET LTC, Set amount:) that are dead for the same
reason but don't carry that marker yet since Xcode hasn't re-run
extraction since they dropped out of source.

Verified with an exact-quote-literal search across
.swift/.m/.h/.storyboard/.xib that none of these 22 keys is actually
referenced anywhere in the codebase (a plain substring grep gives
false positives for several of these - e.g. Currency matches inside
SupportedFiatCurrency - hence the stricter check):

GET LTC / Set amount: /  Each emoji must be different. / Currency /
Enter your current PIN. / Enter your new PIN. / Exchange Rate /
Litecoin Display Unit / Loading Wallet / Paper Key / Re-Enter PIN /
Re-Enter your new PIN. / Ready, Set, Go! / Remember this PIN... /
Settings / Submit / The words entered do not match... /
This is your Brainwallet phrase... /
To make sure everything was written down correctly... / TOP SECRET /
Word / Your PIN will be used to unlock...

Most look like leftovers from the old PIN-entry and seed-phrase
confirmation flows that the "New ..." screens replaced, plus the
recent BuyReceiveView relayout (GET LTC / Set amount:).

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>
…Y MOONPAY

These three keys were sitting in the catalog with empty localizations
(auto-added by Xcode's extractor when it first saw the strings from
the BuyReceiveView relayout, but never filled in), which meant every
non-English locale fell back to the raw English source string.

Translated all 21 supported locales for each key, based on this
catalog's own already-established terminology where it existed:
- BUY / RECEIVE and COPY NEW ADDRESS reuse the wording from the
  existing Buy/Receive and COPY / SHARE / New address copied keys
- POWERED BY MOONPAY is new (MoonPay is a brand name, left
  untranslated; "powered by" uses each locale's standard phrasing)

Also removes "Buy/Receive", the old pre-relayout key: it has zero
source references and its generated symbol collided with the new
BUY / RECEIVE key, which failed the build ("This string key would
generate the same symbol as ...").

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>
Also backfills the v3.9.16 entry, which never made it into develop's
README - release/v3.9.16 added it (adb9dc8) but that branch was never
merged back, so this lineage's Release Notes section jumped straight
from the intro to v3.9.15.

v3.9.17 covers: the BuyReceiveView Android-parity relayout (#177),
the remaining deprecation/dead-code/warnings cleanup (#174, #175),
dropping CircleCI in favor of Xcode Cloud (#173), bw-gdlib v1.6.9
and Modules/core bumps (#171, #176), and the Localizable.xcstrings
dead-key removal + missing-translation additions.

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>
Disposable branch, not built by Xcode Cloud: main only ever receives
squash-merges, so it's disjoint from develop/release branches after
each git-filter rewrite. This exists purely so GitHub can compute a
PR diff between the release content and main; it must never be pushed
to release/v3.9.17 or develop themselves, since Xcode Cloud's clone
step fails on the resulting unrelated-histories graph (see the
analogous release/v3.9.16-into-main precedent, commit bacb136).

Co-Authored-By: grunt-claude-bot <308083480+grunt-claude-bot@users.noreply.github.com>
Co-Authored-By: kcw-grunt <mrkerrywashington@icloud.com>

@kcw-grunt kcw-grunt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Wooo hoo! 👍

@kcw-grunt

Copy link
Copy Markdown
Collaborator

Closing after refactor

@kcw-grunt kcw-grunt closed this Aug 22, 2026
@kcw-grunt
kcw-grunt deleted the release/v3.9.17-into-main branch August 22, 2026 21:47
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.

3 participants