Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MOB-2167 - Fix UI when user's PK is unavailable #644

Merged
merged 2 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ struct UDWallet: Codable, Hashable {
}
}

func getMnemonicsThrowing() throws -> String {
guard let mnemonics = getMnemonics() else { throw Error.failedToRetrieveSP }

return mnemonics
}

func getPrivateKeyThrowing() throws -> String {
guard let privateKey = getPrivateKey() else { throw Error.failedToRetrievePK }

return privateKey
}

private var walletConnectionInfo: WalletConnectionInfo?

func getExternalWallet() -> WCWalletsProvider.WalletRecord? {
Expand Down Expand Up @@ -96,6 +108,8 @@ struct UDWallet: Codable, Hashable {
enum Error: String, Swift.Error, RawValueLocalizable {
case failedSignature
case failedToFindMPCMetadata
case failedToRetrieveSP
case failedToRetrievePK
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ struct UDWallet: Codable, @unchecked Sendable {
case failedToFindWallet = "Failed to Find a Wallet"
case failedSignature
case failedToFindMPCMetadata
case failedToRetrievePK
case failedToRetrieveSP
}

struct WalletConnectionInfo: Codable {
Expand Down Expand Up @@ -72,6 +74,12 @@ struct UDWallet: Codable, @unchecked Sendable {
}
}

func getPrivateKeyThrowing() throws -> String {
guard let privateKey = getPrivateKey() else { throw Error.failedToRetrievePK }

return privateKey
}

func getPrivateKey() -> String? {
guard let ethWallet = self.ethWallet else { return nil }
switch ethWallet.securityType {
Expand All @@ -86,6 +94,12 @@ struct UDWallet: Codable, @unchecked Sendable {
}
}

func getMnemonicsThrowing() throws -> String {
guard let mnemonics = getMnemonics() else { throw Error.failedToRetrieveSP }

return mnemonics
}

func getMnemonics() -> String? {
guard let ethWallet = self.ethWallet else { return nil }
switch ethWallet.securityType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,8 @@ extension String {
static let recoveryPhraseHelpText = "RECOVERY_PHRASE_HELP_TEXT"
static let recoveryPhraseHelpTextHighlighted = "RECOVERY_PHRASE_HELP_TEXT_HIGHLIGHTED"
static let recoveryPhraseHelpTextBullets = "RECOVERY_PHRASE_HELP_TEXT_BULLETS"
static let recoveryPhraseNotAvailableTitle = "RECOVERY_PHRASE_NOT_AVAILABLE_TITLE"
static let recoveryPhraseNotAvailableMessage = "RECOVERY_PHRASE_NOT_AVAILABLE_MESSAGE"

static let confirmYourWords = "CONFIRM_YOUR_WORDS"
static let iForgotMyWords = "I_FORGOT_MY_WORDS"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,22 +88,30 @@ extension BaseRecoveryPhrasePresenter: RecoveryPhrasePresenterProtocol {
// MARK: - Private methods
private extension BaseRecoveryPhrasePresenter {
func configureMnem() {
guard let wallet = self.wallet else { return }

switch recoveryType {
case .privateKey:
guard let privateKey = wallet.getPrivateKey() else { return }

self.privateKey = privateKey
view?.setPrivateKey(privateKey)
case .recoveryPhrase:
guard let mnem = wallet.getMnemonics()?.mnemonicsArray else { return }
do {
guard let wallet = self.wallet else {
throw BaseRecoveryPhrasePresenterError.failedToGetPK
}

configure(with: mnem)
switch recoveryType {
case .privateKey:
let privateKey = try wallet.getPrivateKeyThrowing()
self.privateKey = privateKey
view?.setPrivateKey(privateKey)
case .recoveryPhrase:
let seedPhrase = try wallet.getMnemonicsThrowing()
let mnem = seedPhrase.mnemonicsArray

try configure(with: mnem)
}
} catch {
view?.setRecoveryPhraseUnavailable()
}
}

func configure(with mnem: [String]) {

func configure(with mnem: [String]) throws {
guard mnem.count == 12 else { throw BaseRecoveryPhrasePresenterError.incorrectMnemonicsCount }

self.mnems = mnem

let leftMnems = Array(mnem[0...5])
Expand All @@ -119,4 +127,13 @@ private extension BaseRecoveryPhrasePresenter {
self?.view?.setCopiedToClipboardButtonForState(false)
}
}

enum BaseRecoveryPhrasePresenterError: String, LocalizedError {
case failedToGetPK
case incorrectMnemonicsCount

public var errorDescription: String? {
return rawValue
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ protocol RecoveryPhraseViewControllerProtocol: BaseViewControllerProtocol & View
func setDoneButtonTitle(_ title: String)
func setDoneButtonHidden(_ isHidden: Bool)
func setSubtitleHidden(_ isHidden: Bool)
func setRecoveryPhraseUnavailable()
}

final class RecoveryPhraseViewController: BaseViewController, TitleVisibilityAfterLimitNavBarScrollingBehaviour, BlurVisibilityAfterLimitNavBarScrollingBehaviour {

@IBOutlet private weak var titleLabel: UDTitleLabel!
@IBOutlet private weak var subtitleLabel: UILabel!
@IBOutlet private weak var subTitleButton: UIButton!
@IBOutlet private weak var mnemonicsContainerView: UIView!
@IBOutlet private weak var copyToClipboardButton: TextButton!
Expand Down Expand Up @@ -127,6 +129,17 @@ extension RecoveryPhraseViewController: RecoveryPhraseViewControllerProtocol {
func setSubtitleHidden(_ isHidden: Bool) {
subTitleButton.isHidden = isHidden
}

func setRecoveryPhraseUnavailable() {
mnemonicsContainerView.isHidden = true
subtitleLabel.isHidden = false
subtitleLabel.setAttributedTextWith(text: String.Constants.recoveryPhraseNotAvailableMessage.localized(),
font: .currentFont(withSize: 17, weight: .regular),
textColor: .foregroundDefault,
alignment: .center)
titleLabel.setTitle(String.Constants.recoveryPhraseNotAvailableTitle.localized())
setExplanationText("")
}
}

// MARK: - UIScrollViewDelegate
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
Expand All @@ -23,6 +23,7 @@
<outlet property="rightMnemonicsStackView" destination="C11-lc-vJS" id="zkY-NN-np0"/>
<outlet property="scrollView" destination="oC6-m2-C7e" id="2i9-mY-YDj"/>
<outlet property="subTitleButton" destination="bTU-8r-Yhd" id="FnT-db-JQa"/>
<outlet property="subtitleLabel" destination="46e-pQ-bnf" id="K7m-eb-Ptk"/>
<outlet property="titleLabel" destination="e1C-oj-gDw" id="drZ-KB-Tzf"/>
<outlet property="view" destination="d7V-7Z-4i9" id="eTd-bL-ibX"/>
<outletCollection property="blurCoverViews" destination="wUh-Vu-LXP" collectionClass="NSMutableArray" id="VrF-Xa-wRx"/>
Expand All @@ -35,7 +36,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oC6-m2-C7e">
<rect key="frame" x="0.0" y="44" width="414" height="818"/>
<rect key="frame" x="0.0" y="48" width="414" height="814"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="1Ca-eN-xu2">
<rect key="frame" x="0.0" y="0.0" width="414" height="1"/>
Expand All @@ -45,19 +46,25 @@
</constraints>
</view>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" spacing="32" translatesAutoresizingMaskIntoConstraints="NO" id="KYo-Fj-F2E">
<rect key="frame" x="16" y="60" width="382" height="1108.5"/>
<rect key="frame" x="16" y="60" width="382" height="1145.5"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="PVW-Lw-nI0">
<rect key="frame" x="81.5" y="0.0" width="219.5" height="83.5"/>
<rect key="frame" x="70.5" y="0.0" width="241.5" height="120.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Recovery phrase" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="e1C-oj-gDw" customClass="UDTitleLabel" customModule="domains_manager_ios" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="219.5" height="33.5"/>
<rect key="frame" x="11" y="0.0" width="219.5" height="33.5"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="28"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="46e-pQ-bnf">
<rect key="frame" x="100" y="41.5" width="41.5" height="0.0"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bTU-8r-Yhd">
<rect key="frame" x="19" y="49.5" width="181.5" height="34"/>
<rect key="frame" x="0.0" y="49.5" width="241.5" height="71"/>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" button="YES" notEnabled="YES"/>
<bool key="isElement" value="NO"/>
Expand All @@ -70,7 +77,7 @@
</subviews>
</stackView>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="av9-7g-LPy">
<rect key="frame" x="43" y="115.5" width="296" height="894"/>
<rect key="frame" x="43" y="152.5" width="296" height="894"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="MFp-xX-3FX">
<rect key="frame" x="0.0" y="0.0" width="296" height="894"/>
Expand Down Expand Up @@ -488,7 +495,7 @@
</userDefinedRuntimeAttributes>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="t4J-o6-fm7">
<rect key="frame" x="3" y="1041.5" width="376.5" height="67"/>
<rect key="frame" x="3" y="1078.5" width="376.5" height="67"/>
<string key="text">For your eyes only! Anyone who has access to your 12 word recovery phrase can access your entire wallet. Store your recovery phrase somewhere safe.
Learn more</string>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
Expand Down Expand Up @@ -544,7 +551,7 @@ Learn more</string>
</view>
</objects>
<resources>
<image name="checkCircle" width="20" height="20"/>
<image name="checkCircle" width="56" height="57"/>
<namedColor name="backgroundOverlay">
<color red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
Expand All @@ -555,7 +562,7 @@ Learn more</string>
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
<systemColor name="systemGreenColor">
<color red="0.20392156862745098" green="0.7803921568627451" blue="0.34901960784313724" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color red="0.20392156859999999" green="0.78039215689999997" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
</resources>
</document>
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@
"RECOVERY_PHRASE_HELP_TEXT" = "A recovery phrase is the human-readable form of your wallet private key — the unique, secret passcode used to authenticate and encrypt your wallet access. This phrase allows you to sign transactions, confirm ownership of your Web3 domains, and recover them in the event that your mobile device is lost, stolen, or becomes inaccessible.\n\nHowever you choose to store your recovery phrase, you should consider two things:\n\n• Your 12 word recovery phrase should be safe from other people.\n• Your 12 word recovery phrase should be in a reliable location that you’ll always have access to.\n\nNote: Unstoppable Domains cannot recover your 12 word recovery phrase for you.";
"RECOVERY_PHRASE_HELP_TEXT_HIGHLIGHTED" = "Note: Unstoppable Domains cannot recover your 12 word recovery phrase for you.";
"RECOVERY_PHRASE_HELP_TEXT_BULLETS" = "• Your 12 word recovery phrase should be safe from other people.\n• Your 12 word recovery phrase should be in a reliable location that you’ll always have access to.";
"RECOVERY_PHRASE_NOT_AVAILABLE_TITLE" = "Wallet not available";
"RECOVERY_PHRASE_NOT_AVAILABLE_MESSAGE" = "The app doesn't have access to the secure storage with private keys. If this is a new phone please remove this wallet and import it manually, using the private key or a recovery phrase from your old phone / manually recorded keys.";

// Confirm words screen
"CONFIRM_YOUR_WORDS" = "Confirm your words";
Expand Down