Add development flag `Config.development.shouldPretendIsRealWallet` so we can force watch wallets to proceed to sign (and fail), etc

pull/3928/head
Hwee-Boon Yar 3 years ago
parent 1f92c7beef
commit a657023da6
  1. 12
      AlphaWallet/Browser/Coordinators/DappBrowserCoordinator.swift
  2. 19
      AlphaWallet/Redeem/ViewControllers/TokenCardRedemptionViewController.swift
  3. 2
      AlphaWallet/Settings/Types/Config.swift
  4. 6
      AlphaWallet/Tokens/Collectibles/Coordinators/TokensCardCollectionCoordinator.swift
  5. 21
      AlphaWallet/Tokens/Collectibles/ViewControllers/TokensCardCollectionViewController.swift
  6. 23
      AlphaWallet/Tokens/ViewControllers/TokenInstanceViewController.swift
  7. 21
      AlphaWallet/Tokens/ViewControllers/TokenViewController.swift
  8. 25
      AlphaWallet/Tokens/ViewControllers/TokensCardViewController.swift
  9. 19
      AlphaWallet/Tokens/Views/TokenInstanceWebView.swift
  10. 4
      AlphaWallet/Transactions/Coordinators/TokensCardCoordinator.swift
  11. 18
      AlphaWallet/Transfer/Coordinators/PaymentCoordinator.swift
  12. 7
      AlphaWallet/WalletConnect/Coordinator/WalletConnectCoordinator.swift

@ -517,11 +517,15 @@ extension DappBrowserCoordinator: BrowserViewControllerDelegate {
case .real(let account): case .real(let account):
return performDappAction(account: account) return performDappAction(account: account)
case .watch(let account): case .watch(let account):
switch action { if config.development.shouldPretendIsRealWallet {
case .signTransaction, .sendTransaction, .signMessage, .signPersonalMessage, .signTypedMessage, .signTypedMessageV3, .unknown, .sendRawTransaction:
return rejectDappAction()
case .walletAddEthereumChain, .walletSwitchEthereumChain, .ethCall:
return performDappAction(account: account) return performDappAction(account: account)
} else {
switch action {
case .signTransaction, .sendTransaction, .signMessage, .signPersonalMessage, .signTypedMessage, .signTypedMessageV3, .unknown, .sendRawTransaction:
return rejectDappAction()
case .walletAddEthereumChain, .walletSwitchEthereumChain, .ethCall:
return performDappAction(account: account)
}
} }
} }
} }

@ -114,16 +114,25 @@ class TokenCardRedemptionViewController: UIViewController, TokenVerifiableStatus
case .erc721, .erc721ForTickets: case .erc721, .erc721ForTickets:
redeemData = redeem.redeemMessage(tokenIds: viewModel.tokenHolder.tokens.map({ $0.id })) redeemData = redeem.redeemMessage(tokenIds: viewModel.tokenHolder.tokens.map({ $0.id }))
} }
switch session.account.type { func _generateQr(account: AlphaWallet.Address) {
case .real(let account):
do { do {
guard let decimalSignature = try SignatureHelper.signatureAsDecimal(for: redeemData.message, account: account, analyticsCoordinator: analyticsCoordinator) else { break } guard let decimalSignature = try SignatureHelper.signatureAsDecimal(for: redeemData.message, account: account, analyticsCoordinator: analyticsCoordinator) else { return }
let qrCodeInfo = redeemData.qrCode + decimalSignature let qrCodeInfo = redeemData.qrCode + decimalSignature
imageView.image = qrCodeInfo.toQRCode() imageView.image = qrCodeInfo.toQRCode()
} catch { } catch {
break //no-op
}
}
switch session.account.type {
case .real(let account):
_generateQr(account: account)
case .watch(let account):
//TODO should pass in a Config instance instead
if Config().development.shouldPretendIsRealWallet {
_generateQr(account: account)
} else {
//no-op
} }
case .watch: break
} }
} }

@ -9,6 +9,8 @@ struct Config {
let shouldReadClipboardForWalletConnectUrl = false let shouldReadClipboardForWalletConnectUrl = false
///Useful to reduce network calls ///Useful to reduce network calls
let isAutoFetchingDisabled = false let isAutoFetchingDisabled = false
///Should only be used to allow users to take paths where the current wallet is real, not watched, e.g sign buttons are enabled. Some of those actions will fail, understandably. Should not display a watch wallet as if it is a real wallet though
let shouldPretendIsRealWallet = false
} }
let development = Development() let development = Development()

@ -74,7 +74,7 @@ class TokensCardCollectionCoordinator: NSObject, Coordinator {
navigationController.pushViewController(rootViewController, animated: true) navigationController.pushViewController(rootViewController, animated: true)
refreshUponAssetDefinitionChanges() refreshUponAssetDefinitionChanges()
refreshUponEthereumEventChanges() refreshUponEthereumEventChanges()
} }
private func makeCoordinatorReadOnlyIfNotSupportedByOpenSeaERC1155(type: PaymentFlow, target: IsReadOnlyViewController) { private func makeCoordinatorReadOnlyIfNotSupportedByOpenSeaERC1155(type: PaymentFlow, target: IsReadOnlyViewController) {
switch (type, session.account.type) { switch (type, session.account.type) {
@ -194,7 +194,7 @@ extension TokensCardCollectionCoordinator: TokensCardCollectionViewControllerDel
private func showTokenInstanceActionView(forAction action: TokenInstanceAction, tokenHolder: TokenHolder, viewController: UIViewController) { private func showTokenInstanceActionView(forAction action: TokenInstanceAction, tokenHolder: TokenHolder, viewController: UIViewController) {
delegate?.didTap(for: .send(type: .tokenScript(action: action, tokenObject: token, tokenHolder: tokenHolder)), in: self, viewController: viewController) delegate?.didTap(for: .send(type: .tokenScript(action: action, tokenObject: token, tokenHolder: tokenHolder)), in: self, viewController: viewController)
} }
func didSelectTokenHolder(in viewController: TokensCardCollectionViewController, didSelectTokenHolder tokenHolder: TokenHolder) { func didSelectTokenHolder(in viewController: TokensCardCollectionViewController, didSelectTokenHolder tokenHolder: TokenHolder) {
switch tokenHolder.type { switch tokenHolder.type {
case .collectible: case .collectible:
@ -232,7 +232,7 @@ extension TokensCardCollectionCoordinator: TokensCardCollectionViewControllerDel
viewController.navigationItem.leftBarButtonItem = .backBarButton(self, selector: #selector(didCloseTokenInstanceSelected)) viewController.navigationItem.leftBarButtonItem = .backBarButton(self, selector: #selector(didCloseTokenInstanceSelected))
navigationController.pushViewController(viewController, animated: true) navigationController.pushViewController(viewController, animated: true)
} }
@objc private func didCloseTokenInstanceSelected(_ sender: UIBarButtonItem) { @objc private func didCloseTokenInstanceSelected(_ sender: UIBarButtonItem) {
navigationController.popViewController(animated: true) navigationController.popViewController(animated: true)
} }

@ -151,18 +151,27 @@ class TokensCardCollectionViewController: UIViewController {
buttonsBar.configure(.combined(buttons: viewModel.actions.count)) buttonsBar.configure(.combined(buttons: viewModel.actions.count))
buttonsBar.viewController = self buttonsBar.viewController = self
func _configButton(action: TokenInstanceAction, button: BarButton) {
if let selection = action.activeExcludingSelection(selectedTokenHolder: viewModel.tokenHolders[0], tokenId: viewModel.tokenHolders[0].tokenId, forWalletAddress: session.account.address, fungibleBalance: viewModel.fungibleBalance) {
if selection.denial == nil {
button.displayButton = false
}
}
}
for (action, button) in zip(actions, buttonsBar.buttons) { for (action, button) in zip(actions, buttonsBar.buttons) {
button.setTitle(action.name, for: .normal) button.setTitle(action.name, for: .normal)
button.addTarget(self, action: #selector(actionButtonTapped), for: .touchUpInside) button.addTarget(self, action: #selector(actionButtonTapped), for: .touchUpInside)
switch session.account.type { switch session.account.type {
case .real: case .real:
if let selection = action.activeExcludingSelection(selectedTokenHolder: viewModel.tokenHolders[0], tokenId: viewModel.tokenHolders[0].tokenId, forWalletAddress: session.account.address, fungibleBalance: viewModel.fungibleBalance) { _configButton(action: action, button: button)
if selection.denial == nil {
button.displayButton = false
}
}
case .watch: case .watch:
button.isEnabled = false //TODO pass in Config instance instead
if Config().development.shouldPretendIsRealWallet {
_configButton(action: action, button: button)
} else {
button.isEnabled = false
}
} }
} }
} }

@ -134,19 +134,28 @@ class TokenInstanceViewController: UIViewController, TokenVerifiableStatusViewCo
buttonsBar.configure(.combined(buttons: viewModel.actions.count)) buttonsBar.configure(.combined(buttons: viewModel.actions.count))
buttonsBar.viewController = self buttonsBar.viewController = self
func _configButton(action: TokenInstanceAction, button: BarButton) {
if let selection = action.activeExcludingSelection(selectedTokenHolders: [tokenHolder], forWalletAddress: account.address) {
if selection.denial == nil {
button.displayButton = false
}
}
}
for (index, button) in buttonsBar.buttons.enumerated() { for (index, button) in buttonsBar.buttons.enumerated() {
let action = viewModel.actions[index] let action = viewModel.actions[index]
button.setTitle(action.name, for: .normal) button.setTitle(action.name, for: .normal)
button.addTarget(self, action: #selector(actionButtonTapped), for: .touchUpInside) button.addTarget(self, action: #selector(actionButtonTapped), for: .touchUpInside)
switch account.type { switch account.type {
case .real: case .real:
if let selection = action.activeExcludingSelection(selectedTokenHolders: [tokenHolder], forWalletAddress: account.address) { _configButton(action: action, button: button)
if selection.denial == nil {
button.displayButton = false
}
}
case .watch: case .watch:
button.isEnabled = false //TODO pass in a Config instance instead
if Config().development.shouldPretendIsRealWallet {
_configButton(action: action, button: button)
} else {
button.isEnabled = false
}
} }
} }
} }
@ -231,7 +240,7 @@ extension TokenInstanceViewController: VerifiableStatusViewController {
func open(url: URL) { func open(url: URL) {
delegate?.didPressViewContractWebPage(url, in: self) delegate?.didPressViewContractWebPage(url, in: self)
} }
} }
extension TokenInstanceViewController: TokenInstanceAttributeViewDelegate { extension TokenInstanceViewController: TokenInstanceAttributeViewDelegate {
func didSelect(in view: TokenInstanceAttributeView) { func didSelect(in view: TokenInstanceAttributeView) {

@ -137,18 +137,27 @@ class TokenViewController: UIViewController {
buttonsBar.configure(.combined(buttons: viewModel.actions.count)) buttonsBar.configure(.combined(buttons: viewModel.actions.count))
buttonsBar.viewController = self buttonsBar.viewController = self
func _configButton(action: TokenInstanceAction, viewModel: TokenViewControllerViewModel, button: BarButton) {
if let tokenHolder = generateTokenHolder(), let selection = action.activeExcludingSelection(selectedTokenHolders: [tokenHolder], forWalletAddress: session.account.address, fungibleBalance: viewModel.fungibleBalance) {
if selection.denial == nil {
button.displayButton = false
}
}
}
for (action, button) in zip(actions, buttonsBar.buttons) { for (action, button) in zip(actions, buttonsBar.buttons) {
button.setTitle(action.name, for: .normal) button.setTitle(action.name, for: .normal)
button.addTarget(self, action: #selector(actionButtonTapped), for: .touchUpInside) button.addTarget(self, action: #selector(actionButtonTapped), for: .touchUpInside)
switch session.account.type { switch session.account.type {
case .real: case .real:
if let tokenHolder = generateTokenHolder(), let selection = action.activeExcludingSelection(selectedTokenHolders: [tokenHolder], forWalletAddress: session.account.address, fungibleBalance: viewModel.fungibleBalance) { _configButton(action: action, viewModel: viewModel, button: button)
if selection.denial == nil {
button.displayButton = false
}
}
case .watch: case .watch:
button.isEnabled = false //TODO pass in Config instance instead
if Config().development.shouldPretendIsRealWallet {
_configButton(action: action, viewModel: viewModel, button: button)
} else {
button.isEnabled = false
}
} }
} }
} }

@ -98,7 +98,7 @@ class TokensCardViewController: UIViewController {
assetsPageView.searchBar.delegate = self assetsPageView.searchBar.delegate = self
assetsPageView.collectionView.refreshControl = refreshControl assetsPageView.collectionView.refreshControl = refreshControl
keyboardChecker.constraints = containerView.bottomAnchorConstraints keyboardChecker.constraints = containerView.bottomAnchorConstraints
} }
required init?(coder aDecoder: NSCoder) { required init?(coder aDecoder: NSCoder) {
return nil return nil
@ -156,18 +156,27 @@ class TokensCardViewController: UIViewController {
buttonsBar.configure(.combined(buttons: viewModel.actions.count)) buttonsBar.configure(.combined(buttons: viewModel.actions.count))
buttonsBar.viewController = self buttonsBar.viewController = self
func _configButton(action: TokenInstanceAction, button: BarButton) {
if let selection = action.activeExcludingSelection(selectedTokenHolder: viewModel.tokenHolders[0], tokenId: viewModel.tokenHolders[0].tokenId, forWalletAddress: session.account.address, fungibleBalance: viewModel.fungibleBalance) {
if selection.denial == nil {
button.displayButton = false
}
}
}
for (action, button) in zip(actions, buttonsBar.buttons) { for (action, button) in zip(actions, buttonsBar.buttons) {
button.setTitle(action.name, for: .normal) button.setTitle(action.name, for: .normal)
button.addTarget(self, action: #selector(actionButtonTapped), for: .touchUpInside) button.addTarget(self, action: #selector(actionButtonTapped), for: .touchUpInside)
switch session.account.type { switch session.account.type {
case .real: case .real:
if let selection = action.activeExcludingSelection(selectedTokenHolder: viewModel.tokenHolders[0], tokenId: viewModel.tokenHolders[0].tokenId, forWalletAddress: session.account.address, fungibleBalance: viewModel.fungibleBalance) { _configButton(action: action, button: button)
if selection.denial == nil {
button.displayButton = false
}
}
case .watch: case .watch:
button.isEnabled = false //TODO pass in a Config instance instead
if Config().development.shouldPretendIsRealWallet {
_configButton(action: action, button: button)
} else {
button.isEnabled = false
}
} }
} }
} }
@ -208,7 +217,7 @@ class TokensCardViewController: UIViewController {
viewModel.markHolderSelected() viewModel.markHolderSelected()
guard let tokenHolder = selectedTokenHolder else { return } guard let tokenHolder = selectedTokenHolder else { return }
switch action.type { switch action.type {
case .erc20Send, .erc20Receive, .swap, .buy, .bridge: case .erc20Send, .erc20Receive, .swap, .buy, .bridge:
break break

@ -444,18 +444,27 @@ extension TokenInstanceWebView: WKScriptMessageHandler {
let token = TokensDataStore.token(forServer: server) let token = TokensDataStore.token(forServer: server)
let action = DappAction.fromCommand(.eth(command), server: server, transactionType: .dapp(token, requester)) let action = DappAction.fromCommand(.eth(command), server: server, transactionType: .dapp(token, requester))
switch wallet.type { func _sign(action: DappAction, command: DappCommand, account: AlphaWallet.Address) {
case .real(let account):
switch action { switch action {
case .signPersonalMessage(let hexMessage): case .signPersonalMessage(let hexMessage):
let msg = convertMessageToHex(msg: hexMessage) let msg = convertMessageToHex(msg: hexMessage)
let callbackID = command.id let callbackID = command.id
signMessage(with: .personalMessage(Data(_hex: msg)), account: account, callbackID: callbackID) signMessage(with: .personalMessage(Data(_hex: msg)), account: account, callbackID: callbackID)
case .signTransaction, .sendTransaction, .signMessage, .signTypedMessage, .unknown, .sendRawTransaction, .signTypedMessageV3, .ethCall, .walletAddEthereumChain, .walletSwitchEthereumChain: case .signTransaction, .sendTransaction, .signMessage, .signTypedMessage, .unknown, .sendRawTransaction, .signTypedMessageV3, .ethCall, .walletAddEthereumChain, .walletSwitchEthereumChain:
return break
}
}
switch wallet.type {
case .real(let account):
_sign(action: action, command: command, account: account)
case .watch(let account):
//TODO pass in Config instance instead
if Config().development.shouldPretendIsRealWallet {
_sign(action: action, command: command, account: account)
} else {
//no-op
} }
case .watch:
break
} }
} }
} }

@ -62,7 +62,7 @@ class TokensCardCoordinator: NSObject, Coordinator {
self.eventsDataStore = eventsDataStore self.eventsDataStore = eventsDataStore
self.analyticsCoordinator = analyticsCoordinator self.analyticsCoordinator = analyticsCoordinator
navigationController.navigationBar.isTranslucent = false navigationController.navigationBar.isTranslucent = false
} }
func start() { func start() {
rootViewController.configure() rootViewController.configure()
@ -431,7 +431,7 @@ class TokensCardCoordinator: NSObject, Coordinator {
} }
extension TokensCardCoordinator: TokensCardViewControllerDelegate { extension TokensCardCoordinator: TokensCardViewControllerDelegate {
func didTap(transaction: TransactionInstance, in viewController: TokensCardViewController) { func didTap(transaction: TransactionInstance, in viewController: TokensCardViewController) {
delegate?.didTap(transaction: transaction, in: self) delegate?.didTap(transaction: transaction, in: self)
} }

@ -94,8 +94,7 @@ class PaymentCoordinator: Coordinator {
self.navigationController.setNavigationBarHidden(false, animated: true) self.navigationController.setNavigationBarHidden(false, animated: true)
} }
switch (flow, session.account.type) { func _startPaymentFlow(transactionType: PaymentFlowType) {
case (.send(let transactionType), .real):
switch transactionType { switch transactionType {
case .transaction(let transactionType): case .transaction(let transactionType):
switch transactionType { switch transactionType {
@ -111,14 +110,23 @@ class PaymentCoordinator: Coordinator {
case .tokenScript(let action, let tokenObject, let tokenHolder): case .tokenScript(let action, let tokenObject, let tokenHolder):
startWithTokenScriptCoordinator(action: action, tokenObject: tokenObject, tokenHolder: tokenHolder) startWithTokenScriptCoordinator(action: action, tokenObject: tokenObject, tokenHolder: tokenHolder)
} }
}
switch (flow, session.account.type) {
case (.send(let transactionType), .real):
_startPaymentFlow(transactionType: transactionType)
case (.request, _): case (.request, _):
let coordinator = RequestCoordinator(navigationController: navigationController, account: session.account) let coordinator = RequestCoordinator(navigationController: navigationController, account: session.account)
coordinator.delegate = self coordinator.delegate = self
coordinator.start() coordinator.start()
addCoordinator(coordinator) addCoordinator(coordinator)
case (.send, .watch): case (.send(let transactionType), .watch):
//TODO: This case should be returning an error inCoordinator. Improve this logic into single piece. //TODO pass in a config instance instead
break if Config().development.shouldPretendIsRealWallet {
_startPaymentFlow(transactionType: transactionType)
} else {
//TODO: This case should be returning an error inCoordinator. Improve this logic into single piece.
}
} }
} }

@ -202,7 +202,12 @@ private extension WalletType {
case .real: case .real:
return .value(()) return .value(())
case .watch: case .watch:
return .init(error: WalletConnectCoordinator.RequestCanceledDueToWatchWalletError()) //TODO pass in Config instance instead
if Config().development.shouldPretendIsRealWallet {
return .value(())
} else {
return .init(error: WalletConnectCoordinator.RequestCanceledDueToWatchWalletError())
}
} }
} }
} }

Loading…
Cancel
Save