Skip to content

fix(dashpay): remove unused Firebase Dynamic Links SDK - #1056

Open
QuantumExplorer wants to merge 1 commit into
developfrom
fix/remove-unused-firebase-dynamic-links
Open

fix(dashpay): remove unused Firebase Dynamic Links SDK#1056
QuantumExplorer wants to merge 1 commit into
developfrom
fix/remove-unused-firebase-dynamic-links

Conversation

@QuantumExplorer

Copy link
Copy Markdown
Member

What

Removes the Firebase/DynamicLinks pod and its leftover configuration. Nothing in the app used it, and its only observable effect was sending Google a device fingerprint on first launch.

Why

This came out of a community question in the Russian Telegram group asking whether analytics/tracking are enabled in the new iOS build. There is no analytics SDK in the iOS app — no FirebaseAnalytics, GoogleAppMeasurement, Crashlytics, Mixpanel, Amplitude, Sentry or AppsFlyer is linked, there are zero logEvent/trackEvent call sites, and there is no IDFA/ATT surface. But the audit turned up outbound calls that a privacy-focused user would reasonably call tracking, and this was one of them.

The SDK self-starts and fingerprints the device

[FIRApp configure] runs unconditionally at DashWallet/AppDelegate.m:113. Dynamic Links registers its component with FIRInstantiationTimingEagerInDefaultApp, so configure instantiates it immediately, and the creation block ends with:

if ([FIRDynamicLinks isAutomaticRetrievalEnabled]) {
  [dynamicLinks checkForPendingDynamicLink];
}

isAutomaticRetrievalEnabled returns YES unless FirebaseDeepLinkAutomaticRetrievalEnabled is set in the Info.plist, and neither plist set it. So on the first run after install, the SDK POSTs to firebasedynamiclinks.googleapis.com/v1/installAttribution with a request body containing screen resolution, locale, timezone, device model, iOS version and app installation time — which, combined with the source IP Google observes, is probabilistic install-attribution fingerprinting.

Nothing uses it

There is not a single reference to DynamicLinks, FIRDynamicLinks or handleUniversalLink anywhere outside Pods/. Universal links are already routed directly, and AppDelegate.m says so in continueUserActivity::

Firebase Dynamic Links previously unwrapped these; the service was shut down in 2025, so the invitation URL is now routed directly — normalization/validation happens in the redeem flow (DWInvitationLinkNormalizer + ClaimInvitationScreen).

Google shut Dynamic Links down in August 2025, so the endpoint it fingerprints against is a dead product.

Changes

  • Podfile — replace pod 'Firebase/DynamicLinks' with pod 'Firebase/CoreOnly' in both the dashwallet and dashpay targets.

    The swap matters: CoreOnly is what ships Firebase.h and its module map, which is what @import Firebase; (AppDelegate) and import Firebase (ExploreDatabaseSyncManager) resolve against. It previously arrived implicitly as a dependency of the DynamicLinks subspec, so removing that subspec outright breaks both imports. There is no FirebaseStorage Swift module to fall back on — CocoaPods generates no module map for it, since the pod is not built with modular_headers. Firebase.h reaches Storage through #if __has_include(<FirebaseStorage/FirebaseStorage.h>), and its DynamicLinks branch is guarded the same way, so it simply compiles out. No source imports change.

  • Podfile.lock — regenerated with pod _1.15.2_ install, the version CI pins. The diff is exactly the DynamicLinks removal, Firebase/CoreOnly moving into DEPENDENCIES, and the Podfile checksum. FirebaseCore stays at 8.15.0.

  • DashPay/dashpay-info.plist — remove FirebaseDynamicLinksCustomDomains and FirebaseDeepLinkPasteboardRetrievalEnabled, both of which only configured the removed SDK.

  • DWURLParser.shouldIgnoreURL: — removed, along with its call site in AppDelegate.m. It existed solely to swallow the google://…?match_message=No pre-install link matched for this device. URL that Dynamic Links handed back on first run (commit e5c6011e2, "Ignore dynamic link that comes from Firebase on first run"). With the SDK gone nothing can produce that URL.

Not affected

Invitation handling. invitations.dashpay.io remains in com.apple.developer.associated-domains, continueUserActivity: still routes the universal link straight into DWInvitationLinkNormalizer, and the dashpay://invite scheme path is unchanged. The removed plist key was Dynamic Links' own custom-domain list, not the associated-domains entitlement.

Firebase Storage — the Explore Dash merchant database download from gs://dash-wallet-firebase.appspot.com — is untouched.

Verification

  • xcodebuild -scheme dashpay -sdk iphonesimulator ARCHS=arm64 compiles the two files that import Firebase with no module-resolution errors.
  • pod _1.15.2_ install --deployment — the exact invocation CI uses — reports "Verifying no changes" against the committed lockfile.
  • grep -rn "DynamicLink" over *.swift/*.m/*.h/*.plist outside Pods/ returns nothing.

Full disclosure on the build: it does not reach a successful link in my environment, but the remaining failure is pre-existing on develop and unrelated. It is four errors in EvonodeStatusViewModel.swift (value of type 'SDK' has no member 'getEvonodeStatus', cannot find type 'EvonodeStatus' in scope, 'PlatformMasternode' has no member 'platformDAPIAddress') caused by the local ../platform SwiftDashSDK checkout sitting on an unrelated feature branch that predates that API. I confirmed it by building untouched develop, which produces the identical four errors and nothing else. Since this PR does change what gets linked, please confirm a clean build on a correctly-pinned platform checkout before merging.

Related

Two companion PRs address the other outbound channels found in the same audit: #1053 disables the Firebase diagnostics heartbeat, and #1055 stops a per-foreground IP geolocation lookup to ip-api.com.

🤖 Generated with Claude Code

Nothing in the app referenced Dynamic Links, but the SDK still ran: its
component registers as EagerInDefaultApp, so the unconditional
[FIRApp configure] instantiated it, and automatic retrieval defaults to
enabled because neither Info.plist set
FirebaseDeepLinkAutomaticRetrievalEnabled. On the first run after
install it POSTed to firebasedynamiclinks.googleapis.com/installAttribution
with screen resolution, locale, timezone, device model, iOS version and
app installation time — install-attribution fingerprinting, against a
product Google shut down in 2025.

Invitation universal links already bypass it; continueUserActivity
routes them straight into DWInvitationLinkNormalizer, and the
associated-domains entitlement is untouched.

Depend on Firebase/CoreOnly directly in place of the removed subspec.
CoreOnly ships Firebase.h and its module map, which is what
`@import Firebase` and `import Firebase` resolve against; it previously
arrived implicitly via Firebase/DynamicLinks. FirebaseStorage has no
module map of its own, so dropping the umbrella outright would break
both imports. Firebase.h reaches Storage through __has_include, and
guards its DynamicLinks include the same way, so that branch compiles
out and no source imports change.

Also drops the two Info.plist keys that only configured the removed SDK,
and DWURLParser.shouldIgnoreURL:, which existed solely to swallow the
"No pre-install link matched for this device." URL Dynamic Links handed
back on first run (e5c6011).

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

coderabbitai Bot commented Aug 24, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 54 minutes.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f7cc23bc-1883-4ff2-ac08-9a1dba9d26d9

📥 Commits

Reviewing files that changed from the base of the PR and between bdfb512 and bba0d19.

⛔ Files ignored due to path filters (1)
  • Podfile.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • DashPay/dashpay-info.plist
  • DashWallet/AppDelegate.m
  • DashWallet/Sources/Models/URL Handling/DWURLParser.h
  • DashWallet/Sources/Models/URL Handling/DWURLParser.m
  • Podfile

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

❤️ Share

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

@romchornyi

Copy link
Copy Markdown
Contributor

This will not link: DashWallet.xcodeproj/project.pbxproj carries its own copy of OTHER_LDFLAGS on top of $(inherited), and it still hardcodes -l"FirebaseDynamicLinks" in 8 configurations — dashwallet and dashpay, each in Debug / Release / Testflight / Testnet.

I checked out the branch, ran pod install, and looked at the resolved settings for dashpay/Debug:

  • OTHER_LDFLAGS — the $(inherited) part from Pods-dashpay.debug.xcconfig is correct (DynamicLinks gone), but the pbxproj part that follows still passes -l"FirebaseDynamicLinks".
  • LIBRARY_SEARCH_PATHS — now only FirebaseCore, FirebaseCoreDiagnostics, FirebaseStorage. The FirebaseDynamicLinks directory is gone.

Linking against that combination gives ld: library 'FirebaseDynamicLinks' not found. A stale libFirebaseDynamicLinks.a left in DerivedData does not save it either — it sits in a directory that is no longer on the search path, so a warm local build fails the same way CI does.

This is very likely why your build never reached a successful link. The four EvonodeStatusViewModel.swift errors are compile errors, so the link error is simply masked behind them and has not surfaced yet.

Fix:

sed -i '' '/"-l\\"FirebaseDynamicLinks\\"",/d' DashWallet.xcodeproj/project.pbxproj

I applied that locally and re-checked: OTHER_LDFLAGS is clean for both schemes and every other flag is still supplied by $(inherited).

Two minor things:

  1. pod 'Firebase/CoreOnly' has no version constraint while FirebaseStorage is pinned to 8.15.0. Not a regression (DynamicLinks was unpinned too), but CoreOnly is now the direct source of Firebase.h, so a future pod update could drift the umbrella away from Storage 8.15.0. Worth pinning it to 8.15.0 in both targets.
  2. .claude/agents/EXTERNAL-INTEGRATIONS.md (lines 30, 40-41) still lists Firebase/DynamicLinks as a dependency and shows a DynamicLinks.dynamicLinks() example.

Everything else checks out. The CoreOnly reasoning is right — @import Firebase in AppDelegate.m:23 and import Firebase in ExploreDatabaseSyncManager.swift:18 both need it, FirebaseStorage depends on FirebaseCore rather than the umbrella pod, and Storage still comes through the __has_include guard in Firebase.h. The plist cleanup is complete — no Firebase* key is left in any non-Pods plist. And a fresh pod install here reproduced your Podfile.lock byte for byte apart from the COCOAPODS: version line.

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