Skip to content

Conversation

@zhouxl
Copy link
Collaborator

@zhouxl zhouxl commented Jan 14, 2026

Related Issue

Summary of Changes

Need Regression Testing

  • Yes
  • No

Risk Assessment

  • Low
  • Medium
  • High

Additional Notes

Screenshots (if applicable)

lmcmz and others added 7 commits January 1, 2026 16:17
…on (#2265)

* feat: add headless rn on app launch

* feat: remove event bus pattern

* feat: check blocto keys

* feat: blocto rotation logic

* feat: update Model from RN

* feat: check blocto each time when switch profile

* feat: update route name

* feat: update sign param

* fix: UI error on iOS 26

* feat: dump version 3.0.12

* feat: empty setScreenSecurityLevel

* feat: first filter valid key

---------

Co-authored-by: lmcmz <[email protected]>
# Conflicts:
#	.gitignore
#	FRW.xcodeproj/project.pbxproj
#	FRW/App/AppDelegate.swift
#	FRW/Foundation/Bridge/BridgeModels.swift
#	FRW/Foundation/Bridge/RCTNativeFRWBridge.mm
#	FRW/Foundation/Bridge/TurboModuleSwift.swift
#	FRW/Modules/Login/ViewModel/KeyStoreLoginViewModel.swift
#	FRW/Modules/Login/ViewModel/PrivateKeyLoginViewModel.swift
#	FRW/Modules/Login/ViewModel/SeedPhraseLoginViewModel.swift
#	FRW/Modules/ReactNative/ReactNativeViewController.swift
#	FRW/Services/Manager/UserManager.swift
#	FRW/Services/Manager/Wallet/WalletManager.swift
#	FRW/Services/Router/RouteMap+React.swift
#	Podfile.lock
#	main.jsbundle
@zhouxl zhouxl requested a review from a team as a code owner January 14, 2026 07:03
@github-actions
Copy link

github-actions bot commented Jan 14, 2026

PR Summary

Implemented Blocto key detection service and key rotation workflow integration for iOS. Added a new BloctoDetectorService to detect Blocto keys on user accounts and prompt users with a backup tip when key rotation is needed. Introduced new React Native bridge methods for signing rotation requests, creating seed keys, saving new keys, and removing old keys. Updated version to 3.0.12 and added a new backupTip screen type with corresponding routing. Also fixed a logout issue when a key is available but no profile exists, and improved navigation bar handling for hidden states.

Changes

File Summary
.gitignore Added /assets/__packages to the ignore list.
FRW.xcodeproj/project.pbxproj Added BloctoDetectorService.swift file references and build phases. Updated MARKETING_VERSION from 3.1.0/3.0.11 to 3.0.12 across all targets including main app, notification service extension, and widgets.
FRW/App/AppDelegate.swift Removed an extra blank line in the cleanup method.
FRW/Foundation/Bridge/BridgeModels.swift Added new backupTip case to ScreenType enum. Introduced AccountKeySignature struct with fields for public_key, hash_algo, sign_algo, signature, sign_message, and weight. Reorganized enum declarations.
FRW/Foundation/Bridge/RCTNativeFRWBridge.mm Added Objective-C bridge methods: signRotationRequest:signatureData:resolve:reject:, removeOldKey:publicKey:resolve:reject:, createSeedKey:resolve:reject:, and saveNewKey:resolve:reject: to support key rotation workflow from React Native.
FRW/Foundation/Bridge/TurboModuleSwift.swift Added createSeedKey to generate a new seed phrase and derive a Flow public key. Added saveNewKey to persist seed phrase securely. Added signRotationRequest to sign rotation data with current account key. Added removeOldKey to delete old key from keychain. Added Flow.HashAlgorithm extension for hashing.
FRW/Foundation/Model/Error.swift Renamed invaildPublicKey to invalidPublicKey (typo fix). Added new invalidSignData error case to WalletError enum.
FRW/Modules/Login/ViewModel/LoginViewModelProtocol.swift Updated key matching logic to filter keys with weight >= 1000 and !revoked before selecting the first matching key. Simplified the crypto key nil check.
FRW/Modules/MultiRestore/ViewModel/RestoreMultiConnectViewModel.swift Updated error reference from WalletError.invaildPublicKey to WalletError.invalidPublicKey.
FRW/Modules/PushAlert/PushAlertView.swift Added isNavigationBarHidden property returning true to hide the navigation bar.
FRW/Modules/ReactNative/ReactNativeViewController.swift Added keyRotationTip case to Route enum. Added initialRouteOverride property. Updated viewDidLoad to hide navigation bar. Extended RNBridge.InitialProps.route to handle backupTip screen type mapping to keyRotationTip route.
FRW/Services/Manager/UserManager.swift Changed await WalletManager.shared.updateKeyProvider(provider:) to synchronous call WalletManager.shared.updateKeyProvider(provider:).
FRW/Services/Manager/Wallet/BloctoDetectorService.swift New file implementing BloctoDetectorService with detectBloctoKey(address:) method. Detects Blocto keys by checking for ECDSA_SECP256k1/SHA3_256 keys with weights 999 and 1. Returns BloctoDetectionResult with isBlocto, needRevoke, and revokeKeyIndexes. Caches non-Blocto results.
FRW/Services/Manager/Wallet/WalletManager.swift Added checkBloctoKeyAndPresentBackupTip(address:) method that calls BloctoDetectorService.detectBloctoKey and routes to backup tip screen if rotation is needed. Called when switching to main account or during account setup.
FRW/Services/Router/RouteMap+React.swift Added backupTip case to RouteMap.ReactNative enum. Implemented routing to present ReactNativeViewController with backupTip screen type in fullscreen modal presentation.
FRW/Services/Router/RouteableUIHostingController.swift Moved backItem to a private property. Updated viewWillAppear to conditionally set or clear leftBarButtonItem based on isNavigationBarHidden state to prevent back button showing when navigation bar is hidden.
main.jsbundle Updated React Native JavaScript bundle (binary file).

autogenerated by presubmit.ai

@github-actions
Copy link

github-actions bot commented Jan 14, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

🚨 Pull request needs attention.

Review Summary

Commits Considered (7)
  • 5ba7048: feat: update RN
  • c8e3a5b: Merge branch 'hotfix/3.0.12' into dev-copy

Conflicts:

.gitignore

FRW.xcodeproj/project.pbxproj

FRW/App/AppDelegate.swift

FRW/Foundation/Bridge/BridgeModels.swift

FRW/Foundation/Bridge/RCTNativeFRWBridge.mm

FRW/Foundation/Bridge/TurboModuleSwift.swift

FRW/Modules/Login/ViewModel/KeyStoreLoginViewModel.swift

FRW/Modules/Login/ViewModel/PrivateKeyLoginViewModel.swift

FRW/Modules/Login/ViewModel/SeedPhraseLoginViewModel.swift

FRW/Modules/ReactNative/ReactNativeViewController.swift

FRW/Services/Manager/UserManager.swift

FRW/Services/Manager/Wallet/WalletManager.swift

FRW/Services/Router/RouteMap+React.swift

Podfile.lock

main.jsbundle

  • 5e4cde3: Hotfix/1064 ios integration implement key rotation workflow integration (#2265)
  • feat: add headless rn on app launch

  • feat: remove event bus pattern

  • feat: check blocto keys

  • feat: blocto rotation logic

  • feat: update Model from RN

  • feat: check blocto each time when switch profile

  • feat: update route name

  • feat: update sign param

  • fix: UI error on iOS 26

  • feat: dump version 3.0.12

  • feat: empty setScreenSecurityLevel

  • feat: first filter valid key


Co-authored-by: lmcmz [email protected]

  • 158f1de: feat: replace coinbase url (#1989)
  • eb05d19: feat: revert podfile.lock
  • 953d4ec: Bump version 3.0.11
  • 51fad35: fix: logout issue when key is available but no profile
Files Processed (16)
  • .gitignore (1 hunk)
  • FRW.xcodeproj/project.pbxproj (19 hunks)
  • FRW/App/AppDelegate.swift (1 hunk)
  • FRW/Foundation/Bridge/BridgeModels.swift (4 hunks)
  • FRW/Foundation/Bridge/RCTNativeFRWBridge.mm (2 hunks)
  • FRW/Foundation/Bridge/TurboModuleSwift.swift (4 hunks)
  • FRW/Foundation/Model/Error.swift (1 hunk)
  • FRW/Modules/MultiRestore/ViewModel/RestoreMultiConnectViewModel.swift (1 hunk)
  • FRW/Modules/PushAlert/PushAlertView.swift (1 hunk)
  • FRW/Modules/ReactNative/ReactNativeViewController.swift (5 hunks)
  • FRW/Services/Manager/UserManager.swift (1 hunk)
  • FRW/Services/Manager/Wallet/BloctoDetectorService.swift (1 hunk)
  • FRW/Services/Manager/Wallet/WalletManager.swift (3 hunks)
  • FRW/Services/Router/RouteMap+React.swift (2 hunks)
  • FRW/Services/Router/RouteableUIHostingController.swift (4 hunks)
  • main.jsbundle (0 hunks)
Actionable Comments (2)
  • FRW/Services/Manager/Wallet/BloctoDetectorService.swift [31-31]

    possible bug: "Hash algorithm mismatch between detection and key creation."

  • FRW/Services/Manager/Wallet/WalletManager.swift [257-258]

    possible bug: "Duplicate assignment overwrites conditional logic."

Skipped Comments (4)
  • FRW/Foundation/Bridge/TurboModuleSwift.swift [152-158]

    enhancement: "Missing validation for mnemonic strength parameter."

  • FRW/Foundation/Bridge/TurboModuleSwift.swift [554-565]

    maintainability: "Unused private extension method."

  • FRW/Services/Manager/Wallet/BloctoDetectorService.swift [43-43]

    possible issue: "Cache persistence may cause stale data issues."

  • FRW/Foundation/Bridge/TurboModuleSwift.swift [155-156]

    maintainability: "Incomplete TODO comment left in production code."

let account = try await FlowNetwork.getAccountAtLatestBlock(address: normalized)
let keys = account.keys
let candidateKeys = keys.filter {
$0.signAlgo == .ECDSA_SECP256k1 && $0.hashAlgo == .SHA3_256

Choose a reason for hiding this comment

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

The detection logic checks for SHA3_256 hash algorithm, but the createSeedKey function in TurboModuleSwift.swift creates keys with SHA2_256. This inconsistency might cause issues where newly created keys don't match the detection criteria, or the detection logic may not correctly identify all Blocto keys.

Comment on lines 257 to +258
}
selectedAccount = .main(account.address)

Choose a reason for hiding this comment

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

The line selectedAccount = .main(account.address) is duplicated. The first assignment on line 256 (in the else branch) is immediately overwritten by this unconditional assignment, making the conditional logic above ineffective.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

🚨 Pull request needs attention.

Review Summary

Commits Considered (2)
Files Processed (11)
  • .gitignore (1 hunk)
  • FRW.xcodeproj/project.pbxproj (19 hunks)
  • FRW/App/AppDelegate.swift (1 hunk)
  • FRW/Foundation/Bridge/BridgeModels.swift (4 hunks)
  • FRW/Foundation/Bridge/RCTNativeFRWBridge.mm (2 hunks)
  • FRW/Foundation/Bridge/TurboModuleSwift.swift (4 hunks)
  • FRW/Foundation/Model/Error.swift (1 hunk)
  • FRW/Modules/Login/ViewModel/LoginViewModelProtocol.swift (2 hunks)
  • FRW/Modules/MultiRestore/ViewModel/RestoreMultiConnectViewModel.swift (1 hunk)
  • FRW/Modules/PushAlert/PushAlertView.swift (1 hunk)
  • FRW/Modules/ReactNative/ReactNativeViewController.swift (5 hunks)
Actionable Comments (1)
  • FRW/Modules/Login/ViewModel/LoginViewModelProtocol.swift [167-168]

    possible issue: "Behavioral change in key filtering logic may break existing functionality."

Skipped Comments (5)
  • FRW/Foundation/Bridge/TurboModuleSwift.swift [152-158]

    possible issue: "Missing validation for BIP39 strength parameter."

  • FRW/Foundation/Bridge/TurboModuleSwift.swift [155-156]

    maintainability: "Incomplete TODO comment left in production code."

  • FRW/Foundation/Bridge/TurboModuleSwift.swift [554-565]

    maintainability: "Unused private extension method."

  • FRW/Modules/Login/ViewModel/LoginViewModelProtocol.swift [155-158]

    possible bug: "Guard statement checks nil but doesn't bind the value."

  • FRW/Modules/ReactNative/ReactNativeViewController.swift [27-27]

    maintainability: "Unused property stored but never referenced."

Comment on lines +167 to +168
let filteredKeys = matchingKeys.filter { $0.weight >= 1000 && !$0.revoked }
guard let selectedKey = filteredKeys.first else {

Choose a reason for hiding this comment

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

The logic now filters keys by weight >= 1000 and !revoked, but the original code selected from matchingKeys without these filters. This is a behavioral change that could cause login failures for users with keys that have lower weights or have been revoked but were previously accepted.

@zhouxl zhouxl merged commit 3b5c335 into dev Jan 14, 2026
4 checks passed
@zhouxl zhouxl deleted the dev-copy branch January 14, 2026 07:13
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