Skip to content

Commit

Permalink
Merge branch 'development' into dev/feat/purchase_domains/MOB-2139-bu…
Browse files Browse the repository at this point in the history
…y-multiple

# Conflicts:
#	unstoppable-ios-app/domains-manager-ios/SwiftUI/ViewModifiers/ViewPullUp/ViewPullUpDefaultConfiguration.swift
  • Loading branch information
Oleg-Pecheneg committed Aug 15, 2024
2 parents 69bce59 + c085cd8 commit 3a9aabc
Show file tree
Hide file tree
Showing 19 changed files with 2,793 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ struct WCWalletsProvider {
return self.mobile.native
}

func getUniversalAppLink() -> String? {
guard self.mobile.universal != "" else {
return self.mobile.native
func getOperationalAppLink() -> String? {
guard self.mobile.universal != "" && self.mobile.universal != nil else {
return getNativeAppLink()
}
return self.mobile.universal
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,26 +319,7 @@ extension UDWallet {
var address: String { getActiveAddress(for: .UNS) ?? "" }
}

extension UDWallet {
func launchExternalWallet() async throws {
guard let wcWallet = self.walletConnectionInfo?.externalWallet,
let nativePrefix = wcWallet.getNativeAppLink(),
let url = URL(string: nativePrefix) else {
throw WalletConnectRequestError.failedToFindExternalAppLink
}

try await withCheckedThrowingContinuation { (completion: CheckedContinuation<Void, Swift.Error>) in
DispatchQueue.main.async {
guard UIApplication.shared.canOpenURL(url) else {
completion.resume(throwing: WalletConnectRequestError.failedOpenExternalApp)
return
}
UIApplication.shared.open(url, options: [:], completionHandler: nil)
completion.resume(returning: ())
}
}
}

extension UDWallet {
func getExternalWallet() -> WCWalletsProvider.WalletRecord? {
walletConnectionInfo?.externalWallet
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ extension Error {
case .messageSignDisabled = mpcError {
title = String.Constants.mpcWalletSigningUnavailableErrorMessage.localizedMPCProduct()
message = String.Constants.tryAgainLater.localized()
} else if let mpcError = self as? MPCWalletError,
case .maintenanceEnabled = mpcError {
title = String.Constants.mpcMaintenanceMessageTitle.localizedMPCProduct()
message = String.Constants.mpcMaintenanceMessageSubtitle.localized()
} else {
title = String.Constants.somethingWentWrong.localized()
message = String.Constants.pleaseTryAgain.localized()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1332,6 +1332,14 @@ extension String {
static let sendCryptoMaintenanceMessageSubtitle = "SEND_CRYPTO_MAINTENANCE_MESSAGE_SUBTITLE"
static let signMessagesMaintenanceMessageTitle = "SIGN_MESSAGES_MAINTENANCE_MESSAGE_TITLE"
static let signMessagesMaintenanceMessageSubtitle = "SIGN_MESSAGES_MAINTENANCE_MESSAGE_SUBTITLE"
static let transferDomainsFromVaultMaintenanceMessageTitle = "TRANSFER_DOMAINS_FROM_VAULT_MAINTENANCE_MESSAGE_TITLE"
static let transferDomainsFromVaultMaintenanceMessageSubtitle = "TRANSFER_DOMAINS_FROM_VAULT_MAINTENANCE_MESSAGE_SUBTITLE"
static let mpcMaintenanceMessageTitle = "MPC_MAINTENANCE_MESSAGE_TITLE"
static let mpcMaintenanceMessageSubtitle = "MPC_MAINTENANCE_MESSAGE_SUBTITLE"

// Connect Ledger with MM
static let connectedLedgerWithMMPullUpTitle = "CONNECT_LEDGER_WITH_MM_PULL_UP_TITLE"
static let connectedLedgerWithMMPullUpSubtitle = "CONNECT_LEDGER_WITH_MM_PULL_UP_SUBTITLE"
}

enum SystemImage: String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ extension ConnectExternalWalletViewPresenter: ConnectExternalWalletViewPresenter

switch item {
case .externalWallet(let description):
if description.walletRecord.make == .ledgerLive {
showConnectLedgerWithMM()
return
}

let wcWalletSelected = description.walletRecord
logButtonPressedAnalyticEvents(button: .externalWalletSelected, parameters: [.externalWallet: wcWalletSelected.name])

Expand Down Expand Up @@ -117,6 +122,12 @@ private extension ConnectExternalWalletViewPresenter {
view?.applySnapshot(snapshot, animated: true)
}
}

func showConnectLedgerWithMM() {
guard let view else { return }

appContext.pullUpViewService.showConnectLedgerWithMMPullUp(in: view)
}
}

extension ConnectExternalWalletViewPresenter {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,9 @@ private extension DomainProfileViewPresenter {
} else if let error = errors.compactMap({ $0.error as? MPCWalletError }).first(where: { $0 == .messageSignDisabled }) {
view.showAlertWith(error: error, handler: nil)
throw MPCWalletError.messageSignDisabled
} else if let error = errors.compactMap({ $0.error as? MPCWalletError }).first(where: { $0 == .maintenanceEnabled }) {
view.showAlertWith(error: error, handler: nil)
throw MPCWalletError.maintenanceEnabled
} else {
try await requiredPullUp()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ private extension WalletTransactionDisplayInfoListItemView {

@ViewBuilder
func gasFeeLabel() -> some View {
if transaction.gas > 0 {
if transaction.gas > 0,
!transaction.type.isDeposit {
Text("-\(transaction.gas.formatted(toMaxNumberAfterComa: 4)) " + String.Constants.txFee.localized())
.font(.currentFont(size: 14))
.foregroundStyle(Color.foregroundSecondary)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ private extension HomeWalletView {
}

func walletActions() -> [WalletAction] {
var actions: [WalletAction] = [.buy(enabled: viewModel.isBuyButtonEnabled)]
var actions: [WalletAction] = []
if viewModel.isBuyButtonEnabled {
actions.append(.buy(enabled: true))
}
if viewModel.isSendCryptoEnabled {
actions.append(.send)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ enum MPCWalletError: String, LocalizedError {
case incorrectCode
case incorrectPassword
case messageSignDisabled
case maintenanceEnabled

public var errorDescription: String? {
return rawValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ extension MPCWalletsService: MPCWalletsServiceProtocol {
AsyncThrowingStream { continuation in
Task {
do {
try verifyMPCServiceAvailableOrFail()
let subService = try getSubServiceFor(provider: .fireblocksUD)

for try await step in subService.setupMPCWalletWith(code: code,
Expand All @@ -53,6 +54,7 @@ extension MPCWalletsService: MPCWalletsServiceProtocol {

func signPersonalMessage(_ messageString: String,
by walletMetadata: MPCWalletMetadata) async throws -> String {
try verifyMPCServiceAvailableOrFail()
guard udFeatureFlagsService.valueFor(flag: .isMPCSignatureEnabled) else { throw MPCWalletError.messageSignDisabled }
let subService = try getSubServiceFor(provider: walletMetadata.provider)

Expand All @@ -64,6 +66,7 @@ extension MPCWalletsService: MPCWalletsServiceProtocol {
func signTypedDataMessage(_ message: String,
chain: BlockchainType,
by walletMetadata: MPCWalletMetadata) async throws -> String {
try verifyMPCServiceAvailableOrFail()
guard udFeatureFlagsService.valueFor(flag: .isMPCSignatureEnabled) else { throw MPCWalletError.messageSignDisabled }
let subService = try getSubServiceFor(provider: walletMetadata.provider)

Expand Down Expand Up @@ -91,6 +94,7 @@ extension MPCWalletsService: MPCWalletsServiceProtocol {
chain: String,
destinationAddress: String,
by walletMetadata: MPCWalletMetadata) async throws -> String {
try verifyMPCServiceAvailableOrFail()
let subService = try getSubServiceFor(provider: walletMetadata.provider)

return try await subService.transferAssets(amount,
Expand All @@ -105,6 +109,7 @@ extension MPCWalletsService: MPCWalletsServiceProtocol {
chain: BlockchainType,
destinationAddress: String,
by walletMetadata: MPCWalletMetadata) async throws -> String {
try verifyMPCServiceAvailableOrFail()
let subService = try getSubServiceFor(provider: walletMetadata.provider)

return try await subService.sendETHTransaction(data: data,
Expand All @@ -125,6 +130,7 @@ extension MPCWalletsService: MPCWalletsServiceProtocol {
chain: String,
destinationAddress: String,
by walletMetadata: MPCWalletMetadata) async throws -> Double {
try verifyMPCServiceAvailableOrFail()
let subService = try getSubServiceFor(provider: walletMetadata.provider)

return try await subService.fetchGasFeeFor(amount,
Expand All @@ -137,6 +143,14 @@ extension MPCWalletsService: MPCWalletsServiceProtocol {

// MARK: - Private methods
private extension MPCWalletsService {
func verifyMPCServiceAvailableOrFail() throws {
let maintenanceData: MaintenanceModeData? = appContext.udFeatureFlagsService.entityValueFor(flag: .isMaintenanceMPCEnabled)

if maintenanceData?.isCurrentlyEnabled == true {
throw MPCWalletError.maintenanceEnabled
}
}

func getSubServiceFor(provider: MPCWalletProvider) throws -> MPCWalletProviderSubServiceProtocol {
guard let subService = subServices.first(where: { $0.provider == provider }) else {
Debugger.printFailure("Failed to get mpc wallet sub service for provider: \(provider.rawValue)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ private extension SettingsView {

var settingsItemsToShow: [SettingsItems] {
var items = SettingsItems.allCases
if webUser != nil || isEcommMaintenanceEnabled {
if webUser != nil {
items.removeAll(where: { $0 == .viewVaulted })
}
return items
Expand Down Expand Up @@ -390,7 +390,11 @@ private extension SettingsView {
case .legal:
pullUp = .default(.legalSelectionPullUp(selectionCallback: didSelectLegalType))
case .viewVaulted:
pullUp = .default(.loginOptionsSelectionPullUp(selectionCallback: didSelectToAuthWith))
if isEcommMaintenanceEnabled {
pullUp = .default(.transferDomainsFromVaultUnavailable())
} else {
pullUp = .default(.loginOptionsSelectionPullUp(selectionCallback: didSelectToAuthWith))
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,7 @@ extension Analytics {
case removeWalletConfirmation
case connectedExternalWalletInfo
case externalWalletDisconnected, switchExternalWalletConfirmation
case connectLedgerWithMM
case themeSelection
case routeCryptoInfo
case domainRecordsChangesConfirmation
Expand Down Expand Up @@ -517,7 +518,7 @@ extension Analytics {
case copyMultiChainAddresses
case removeMPCWalletConfirmation
case transactionDetails
case domainProfileMaintenance, signMessagesMaintenance
case domainProfileMaintenance, signMessagesMaintenance, transferDomainsFromVaultMaintenance

// Disabled
case walletTransactionsSelection, copyWalletAddressSelection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,9 @@ private extension ExternalWalletConnectionService {

func startExternalWallet(wcWallet: WCWalletsProvider.WalletRecord, connectionUrlString: String?) {
let appPrefix: String
if let universalPrefix = wcWallet.getUniversalAppLink(),
if let universalPrefix = wcWallet.getOperationalAppLink(),
!universalPrefix.isEmpty {
appPrefix = universalPrefix
} else if let nativePrefix = wcWallet.getNativeAppLink(),
!nativePrefix.isEmpty {
appPrefix = nativePrefix
} else {
Debugger.printFailure("Cannot get a Universal or Native link for a wallet \(wcWallet.name)", critical: true)
finishWith(result: .failure(.failedToConnect))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -430,4 +430,18 @@ extension PullUpViewService {
}
}

func showConnectLedgerWithMMPullUp(in viewController: UIViewController) {
let selectionViewHeight: CGFloat = 372
let title = String.Constants.connectedLedgerWithMMPullUpTitle.localized()
let subtitle = String.Constants.connectedLedgerWithMMPullUpSubtitle.localized()
let selectionView = PullUpSelectionView(configuration: .init(title: .text(title),
contentAlignment: .center,
icon: .init(icon: .externalWalletIndicator,
size: .small),
subtitle: .label(.text(subtitle)),
cancelButton: .gotItButton()),
items: PullUpSelectionViewEmptyItem.allCases)

showOrUpdate(in: viewController, pullUp: .connectLedgerWithMM, contentView: selectionView, height: selectionViewHeight)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ protocol PullUpViewServiceProtocol {
func showExternalWalletConnectionHintPullUp(for walletRecord: WCWalletsProvider.WalletRecord,
in viewController: UIViewController) async
func showExternalWalletFailedToSignPullUp(in viewController: UIViewController) async
func showConnectLedgerWithMMPullUp(in viewController: UIViewController)

// MARK: - Domain profile
func showManageDomainRouteCryptoPullUp(in viewController: UIViewController,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ private extension WalletConnectExternalWalletHandler {
@MainActor
func launchExternalWalletAndNotifyListeners(_ wallet: UDWallet) throws {
guard let wcWallet = wallet.getExternalWallet(),
let nativePrefix = wcWallet.getUniversalAppLink(),
let nativePrefix = wcWallet.getOperationalAppLink(),
let url = URL(string: nativePrefix) else {
throw WalletConnectRequestError.failedToFindExternalAppLink
}
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -1226,3 +1226,11 @@ More tabs are coming in the next updates.";
"SEND_CRYPTO_MAINTENANCE_MESSAGE_SUBTITLE" = "We're working to make it available soon.\nMeantime try to switch to another wallet.";
"SIGN_MESSAGES_MAINTENANCE_MESSAGE_TITLE" = "Signing messages is currently unavailable";
"SIGN_MESSAGES_MAINTENANCE_MESSAGE_SUBTITLE" = "We're working to make it available soon.";
"TRANSFER_DOMAINS_FROM_VAULT_MAINTENANCE_MESSAGE_TITLE" = "We'll be back soon";
"TRANSFER_DOMAINS_FROM_VAULT_MAINTENANCE_MESSAGE_SUBTITLE" = "Transferring domains from the vault is temporarily unavailable. Please try again later.";
"MPC_MAINTENANCE_MESSAGE_TITLE" = "We'll be back soon";
"MPC_MAINTENANCE_MESSAGE_SUBTITLE" = "Transferring domains from the vault is temporarily unavailable. Please try again later.";

// Connect Ledger with MM
"CONNECT_LEDGER_WITH_MM_PULL_UP_TITLE" = "Use MetaMask rather than Ledger Live";
"CONNECT_LEDGER_WITH_MM_PULL_UP_SUBTITLE" = "1. Connect your Ledger device to the MetaMask mobile wallet\n2. Connect MetaMask to this app";
Original file line number Diff line number Diff line change
Expand Up @@ -331,10 +331,10 @@ extension ViewPullUpDefaultConfiguration {
dismissCallback: nil)
}

static func showFinishSetupProfilePullUp(pendingProfile: DomainProfilePendingChanges,
signCallback: @escaping MainActorAsyncCallback) -> ViewPullUpDefaultConfiguration {
static func showFinishSetupProfilePullUp(pendingProfile: DomainProfilePendingChanges,
signCallback: @escaping MainActorAsyncCallback) -> ViewPullUpDefaultConfiguration {
let domainName = pendingProfile.domainName

return .init(icon: .init(icon: .infoIcon,
size: .large),
title: .highlightedText(.init(text: String.Constants.finishSetupProfilePullUpTitle.localized(String(domainName.prefix(40))),
Expand Down Expand Up @@ -363,9 +363,9 @@ extension ViewPullUpDefaultConfiguration {
analyticsName: .tryAgain,
action: { completion(.success(Void())) })),
cancelButton: .primaryGhost(content: .init(title: String.Constants.cancelSetup.localized(),
icon: nil,
analyticsName: .cancel,
action: { completion(.failure(PullUpError.dismissed)) })),
icon: nil,
analyticsName: .cancel,
action: { completion(.failure(PullUpError.dismissed)) })),
analyticName: .failedToFinishProfileForPurchasedDomains,
dismissCallback: nil)
}
Expand All @@ -388,7 +388,7 @@ extension ViewPullUpDefaultConfiguration {

static func legalSelectionPullUp(selectionCallback: @escaping (LegalType)->()) -> ViewPullUpDefaultConfiguration {
var selectedItem: LegalType?

return .init(title: .text(String.Constants.settingsLegal.localized()),
items: LegalType.allCases,
itemSelectedCallback: { item in
Expand Down Expand Up @@ -444,7 +444,7 @@ extension ViewPullUpDefaultConfiguration {
analyticName: .noRecordsSetToSendCrypto,
dismissCallback: nil)
}

static func showSendCryptoForTheFirstTimeConfirmationPullUp(confirmCallback: @escaping MainActorAsyncCallback) -> ViewPullUpDefaultConfiguration {
var icon: UIImage?
if User.instance.getSettings().touchIdActivated,
Expand Down Expand Up @@ -492,8 +492,8 @@ extension ViewPullUpDefaultConfiguration {
title: .text(String.Constants.removeMPCWalletPullUpTitle.localizedMPCProduct()),
subtitle: .label(.text(String.Constants.removeMPCWalletPullUpSubtitle.localized())),
actionButton: .primaryDanger(content: .init(title: String.Constants.removeWallet.localized(),
analyticsName: .walletRemove,
action: {
analyticsName: .walletRemove,
action: {
removeCallback()
})),
cancelButton: .secondary(content: .init(title: String.Constants.cancel.localized(),
Expand Down Expand Up @@ -525,6 +525,15 @@ extension ViewPullUpDefaultConfiguration {
action: goToWebCallback)),
analyticName: .wcRequestNotSupported)
}

static func transferDomainsFromVaultUnavailable() -> ViewPullUpDefaultConfiguration {
.init(icon: .init(icon: .hammerWrenchIcon24,
size: .small),
title: .text(String.Constants.transferDomainsFromVaultMaintenanceMessageTitle.localized()),
subtitle: .label(.text(String.Constants.transferDomainsFromVaultMaintenanceMessageSubtitle.localized())),
cancelButton: .gotItButton(),
analyticName: .transferDomainsFromVaultMaintenance)
}
}

// MARK: - Open methods
Expand Down

0 comments on commit 3a9aabc

Please sign in to comment.