Improve adding transaction to db, remove `waiting for closing ui screens` #3061

pull/3064/head
Vladyslav shepitko 3 years ago
parent afa6c899c6
commit e079472e57
  1. 34
      AlphaWallet/Browser/Coordinators/DappBrowserCoordinator.swift
  2. 7
      AlphaWallet/InCoordinator.swift
  3. 8
      AlphaWallet/Tokens/Coordinators/ClaimPaidOrderCoordinator.swift
  4. 6
      AlphaWallet/Tokens/Coordinators/SingleChainTokenCoordinator.swift
  5. 20
      AlphaWallet/Transactions/Coordinators/ReplaceTransactionCoordinator.swift
  6. 6
      AlphaWallet/Transactions/Coordinators/TokensCardCoordinator.swift
  7. 18
      AlphaWallet/Transactions/Coordinators/TransactionDataCoordinator.swift
  8. 5
      AlphaWallet/Transfer/Coordinators/PaymentCoordinator.swift
  9. 9
      AlphaWallet/Transfer/Coordinators/SendCoordinator.swift
  10. 16
      AlphaWallet/Transfer/Coordinators/TransactionConfirmationCoordinator.swift
  11. 8
      AlphaWallet/Transfer/Coordinators/TransferNFTCoordinator.swift
  12. 30
      AlphaWallet/WalletConnect/Controllers/TransactionConfirmationCoordinatorBridgeToPromise.swift
  13. 6
      AlphaWallet/WalletConnect/Coordinator/WalletConnectCoordinator.swift

@ -400,29 +400,33 @@ extension DappBrowserCoordinator: TransactionConfirmationCoordinatorDelegate {
navigationController.dismiss(animated: true)
}
func coordinator(_ coordinator: TransactionConfirmationCoordinator, didCompleteTransaction result: TransactionConfirmationResult) {
func didSendTransaction(_ transaction: SentTransaction, inCoordinator coordinator: TransactionConfirmationCoordinator) {
switch pendingTransaction {
case .data(let callbackID):
let data = Data(_hex: transaction.id)
let callback = DappCallback(id: callbackID, value: .sentTransaction(data))
browserViewController.notifyFinish(callbackID: callbackID, value: .success(callback))
delegate?.didSentTransaction(transaction: transaction, inCoordinator: self)
case .none:
break
}
}
func didFinish(_ result: ConfirmResult, in coordinator: TransactionConfirmationCoordinator) {
coordinator.close { [weak self] in
guard let strongSelf = self, let delegate = strongSelf.delegate else { return }
guard let strongSelf = self else { return }
switch (strongSelf.pendingTransaction, result) {
case (.data(let callbackID), .confirmationResult(let type)):
switch type {
case .signedTransaction(let data):
case (.data(let callbackID), .signedTransaction(let data)):
let callback = DappCallback(id: callbackID, value: .signTransaction(data))
strongSelf.browserViewController.notifyFinish(callbackID: callbackID, value: .success(callback))
//TODO do we need to do this for a pending transaction?
//strongSelf.delegate?.didSentTransaction(transaction: transaction, inCoordinator: strongSelf)
case .sentTransaction(let transaction):
// on send transaction we pass transaction ID only.
let data = Data(_hex: transaction.id)
let callback = DappCallback(id: callbackID, value: .sentTransaction(data))
strongSelf.browserViewController.notifyFinish(callbackID: callbackID, value: .success(callback))
delegate.didSentTransaction(transaction: transaction, inCoordinator: strongSelf)
case .sentRawTransaction:
case (.data, .sentTransaction):
//moved up to `didSendTransaction` function
break
}
case (.none, .noData), (.none, .confirmationResult), (.data, .noData):
case (.none, _), (_, .sentTransaction), (_, .sentRawTransaction):
break
}

@ -1067,13 +1067,16 @@ extension InCoordinator: TokensCoordinatorDelegate {
}
extension InCoordinator: PaymentCoordinatorDelegate {
func didSendTransaction(_ transaction: SentTransaction, inCoordinator coordinator: PaymentCoordinator) {
handlePendingTransaction(transaction: transaction)
}
func didFinish(_ result: ConfirmResult, in coordinator: PaymentCoordinator) {
removeCoordinator(coordinator)
switch result {
case .sentTransaction(let transaction):
handlePendingTransaction(transaction: transaction)
coordinator.dismiss(animated: false)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {

@ -213,10 +213,14 @@ extension ClaimPaidOrderCoordinator: TransactionConfirmationCoordinatorDelegate
removeCoordinator(coordinator)
}
func coordinator(_ coordinator: TransactionConfirmationCoordinator, didCompleteTransaction result: TransactionConfirmationResult) {
func didSendTransaction(_ transaction: SentTransaction, inCoordinator coordinator: TransactionConfirmationCoordinator) {
// no-op
}
func didFinish(_ result: ConfirmResult, in coordinator: TransactionConfirmationCoordinator) {
coordinator.close { [weak self] in
guard let strongSelf = self else { return }
strongSelf.delegate?.coordinator(strongSelf, didCompleteTransaction: result)
strongSelf.delegate?.coordinator(strongSelf, didCompleteTransaction: .confirmationResult(result))
}
removeCoordinator(coordinator)
}

@ -669,7 +669,11 @@ extension SingleChainTokenCoordinator: TransactionConfirmationCoordinatorDelegat
removeCoordinator(coordinator)
}
func coordinator(_ coordinator: TransactionConfirmationCoordinator, didCompleteTransaction result: TransactionConfirmationResult) {
func didSendTransaction(_ transaction: SentTransaction, inCoordinator coordinator: TransactionConfirmationCoordinator) {
//no-op
}
func didFinish(_ result: ConfirmResult, in coordinator: TransactionConfirmationCoordinator) {
coordinator.close { [weak self] in
guard let strongSelf = self else { return }
strongSelf.removeCoordinator(coordinator)

@ -124,24 +124,16 @@ extension ReplaceTransactionCoordinator: TransactionConfirmationCoordinatorDeleg
coordinator.navigationController.displayError(message: error.prettyError)
}
func coordinator(_ coordinator: TransactionConfirmationCoordinator, didCompleteTransaction result: TransactionConfirmationResult) {
func didSendTransaction(_ transaction: SentTransaction, inCoordinator coordinator: TransactionConfirmationCoordinator) {
delegate?.didSendTransaction(transaction, inCoordinator: self)
}
func didFinish(_ result: ConfirmResult, in coordinator: TransactionConfirmationCoordinator) {
coordinator.close { [weak self] in
guard let strongSelf = self else { return }
strongSelf.removeCoordinator(coordinator)
switch result {
case .confirmationResult(let confirmResult):
switch confirmResult {
case .sentTransaction(let transaction):
strongSelf.delegate?.didSendTransaction(transaction, inCoordinator: strongSelf)
case .signedTransaction, .sentRawTransaction:
break
}
case .noData:
break
}
strongSelf.transactionConfirmationResult = result
strongSelf.transactionConfirmationResult = .confirmationResult(result)
let coordinator = TransactionInProgressCoordinator(presentingViewController: strongSelf.presentingViewController)
coordinator.delegate = strongSelf

@ -715,7 +715,11 @@ extension TokensCardCoordinator: TransactionConfirmationCoordinatorDelegate {
removeCoordinator(coordinator)
}
func coordinator(_ coordinator: TransactionConfirmationCoordinator, didCompleteTransaction result: TransactionConfirmationResult) {
func didSendTransaction(_ transaction: SentTransaction, inCoordinator coordinator: TransactionConfirmationCoordinator) {
// no-op
}
func didFinish(_ result: ConfirmResult, in coordinator: TransactionConfirmationCoordinator) {
coordinator.close { [weak self] in
guard let strongSelf = self else { return }
strongSelf.removeCoordinator(coordinator)

@ -34,10 +34,6 @@ class TransactionDataCoordinator: Coordinator {
return queue
}()
weak var delegate: TransactionDataCoordinatorDelegate?
//TODO we do away with the Transactions tab and use Activity tab, we can remove this `delegate2`
weak var delegate2: TransactionDataCoordinatorDelegate?
var coordinators: [Coordinator] = []
init(
@ -73,11 +69,6 @@ class TransactionDataCoordinator: Coordinator {
for each in singleChainTransactionDataCoordinators {
each.start()
}
//Since start() is called at launch, and user don't see the Transactions tab immediately, we don't want it to block launching
DispatchQueue.global().async {
self.handleUpdateItems(reloadImmediately: false)
}
}
@objc private func stopTimers() {
@ -108,7 +99,6 @@ class TransactionDataCoordinator: Coordinator {
let tokensDataStore = tokensStorages[transaction.original.server]
let transaction = Transaction.from(from: session.account.address, transaction: transaction, tokensDataStore: tokensDataStore)
transactionCollection.add([transaction])
handleUpdateItems(reloadImmediately: true)
}
func stop() {
@ -120,16 +110,10 @@ class TransactionDataCoordinator: Coordinator {
private func singleChainTransactionDataCoordinator(forServer server: RPCServer) -> SingleChainTransactionDataCoordinator? {
return singleChainTransactionDataCoordinators.first { $0.isServer(server) }
}
private func handleUpdateItems(reloadImmediately: Bool) {
let objects = transactionCollection.objects
delegate?.didUpdate(result: .success(objects), reloadImmediately: reloadImmediately)
delegate2?.didUpdate(result: .success(objects), reloadImmediately: reloadImmediately)
}
}
extension TransactionDataCoordinator: SingleChainTransactionDataCoordinatorDelegate {
func handleUpdateItems(inCoordinator: SingleChainTransactionDataCoordinator, reloadImmediately: Bool) {
handleUpdateItems(reloadImmediately: reloadImmediately)
// no-op
}
}

@ -4,6 +4,7 @@ import Foundation
import UIKit
protocol PaymentCoordinatorDelegate: class, CanOpenURL {
func didSendTransaction(_ transaction: SentTransaction, inCoordinator coordinator: PaymentCoordinator)
func didFinish(_ result: ConfirmResult, in coordinator: PaymentCoordinator)
func didCancel(in coordinator: PaymentCoordinator)
}
@ -105,6 +106,10 @@ class PaymentCoordinator: Coordinator {
}
extension PaymentCoordinator: SendCoordinatorDelegate {
func didSendTransaction(_ transaction: SentTransaction, inCoordinator coordinator: SendCoordinator) {
delegate?.didSendTransaction(transaction, inCoordinator: self)
}
func didFinish(_ result: ConfirmResult, in coordinator: SendCoordinator) {
delegate?.didFinish(result, in: self)
}

@ -7,6 +7,7 @@ import PromiseKit
import Result
protocol SendCoordinatorDelegate: class, CanOpenURL {
func didSendTransaction(_ transaction: SentTransaction, inCoordinator coordinator: SendCoordinator)
func didFinish(_ result: ConfirmResult, in coordinator: SendCoordinator)
func didCancel(in coordinator: SendCoordinator)
}
@ -151,13 +152,17 @@ extension SendCoordinator: TransactionConfirmationCoordinatorDelegate {
coordinator.navigationController.displayError(message: error.prettyError)
}
func coordinator(_ coordinator: TransactionConfirmationCoordinator, didCompleteTransaction result: TransactionConfirmationResult) {
func didSendTransaction(_ transaction: SentTransaction, inCoordinator coordinator: TransactionConfirmationCoordinator) {
delegate?.didSendTransaction(transaction, inCoordinator: self)
}
func didFinish(_ result: ConfirmResult, in coordinator: TransactionConfirmationCoordinator) {
coordinator.close { [weak self] in
guard let strongSelf = self else { return }
strongSelf.removeCoordinator(coordinator)
strongSelf.transactionConfirmationResult = result
strongSelf.transactionConfirmationResult = .confirmationResult(result)
let coordinator = TransactionInProgressCoordinator(presentingViewController: strongSelf.navigationController)
coordinator.delegate = strongSelf

@ -60,7 +60,8 @@ enum ConfirmResult {
}
protocol TransactionConfirmationCoordinatorDelegate: class, CanOpenURL {
func coordinator(_ coordinator: TransactionConfirmationCoordinator, didCompleteTransaction result: TransactionConfirmationResult)
func didSendTransaction(_ transaction: SentTransaction, inCoordinator coordinator: TransactionConfirmationCoordinator)
func didFinish(_ result: ConfirmResult, in coordinator: TransactionConfirmationCoordinator)
func coordinator(_ coordinator: TransactionConfirmationCoordinator, didFailTransaction error: AnyError)
func didClose(in coordinator: TransactionConfirmationCoordinator)
}
@ -184,7 +185,7 @@ extension TransactionConfirmationCoordinator: TransactionConfirmationViewControl
firstly {
sendTransaction()
}.done { result in
self.showSuccess(result: result)
self.handleSendTransactionSuccessfully(result: result)
self.logCompleteActionSheetForTransactionConfirmationSuccessfully()
self.askUserToRateAppOrSubscribeToNewsletter()
}.catch { error in
@ -207,10 +208,17 @@ extension TransactionConfirmationCoordinator: TransactionConfirmationViewControl
return coordinator.send(transaction: transaction)
}
private func showSuccess(result: ConfirmResult) {
private func handleSendTransactionSuccessfully(result: ConfirmResult) {
switch result {
case .sentTransaction(let tx):
delegate?.didSendTransaction(tx, inCoordinator: self)
case .sentRawTransaction, .signedTransaction:
break
}
confirmationViewController.set(state: .done(withError: false)) {
self.showFeedbackOnSuccess()
self.delegate?.coordinator(self, didCompleteTransaction: .confirmationResult(result))
self.delegate?.didFinish(result, in: self)
}
}

@ -65,6 +65,14 @@ extension TransferNFTCoordinator: TransactionConfirmationCoordinatorDelegate {
func coordinator(_ coordinator: TransactionConfirmationCoordinator, didCompleteTransaction result: TransactionConfirmationResult) {
delegate?.didCompleteTransfer(withTransactionConfirmationCoordinator: coordinator, result: result, inCoordinator: self)
}
func didSendTransaction(_ transaction: SentTransaction, inCoordinator coordinator: TransactionConfirmationCoordinator) {
// no-op
}
func didFinish(_ result: ConfirmResult, in coordinator: TransactionConfirmationCoordinator) {
delegate?.didCompleteTransfer(withTransactionConfirmationCoordinator: coordinator, result: .confirmationResult(result), inCoordinator: self)
}
}
extension TransferNFTCoordinator: CanOpenURL {

@ -17,14 +17,15 @@ private class TransactionConfirmationCoordinatorBridgeToPromise {
private let (promise, seal) = Promise<ConfirmResult>.pending()
private var retainCycle: TransactionConfirmationCoordinatorBridgeToPromise?
private weak var confirmationCoordinator: TransactionConfirmationCoordinator?
private var didSendTransactionClosure: ((SentTransaction) -> Void)?
init(_ navigationController: UINavigationController, session: WalletSession, coordinator: Coordinator & CanOpenURL, analyticsCoordinator: AnalyticsCoordinator) {
init(_ navigationController: UINavigationController, session: WalletSession, coordinator: Coordinator & CanOpenURL, analyticsCoordinator: AnalyticsCoordinator, didSendTransactionClosure: @escaping (SentTransaction) -> Void) {
self.navigationController = navigationController
self.session = session
self.coordinator = coordinator
self.analyticsCoordinator = analyticsCoordinator
retainCycle = self
self.didSendTransactionClosure = didSendTransactionClosure
promise.ensure {
//NOTE: Ensure we break the retain cycle, and remove coordinator from list
self.retainCycle = nil
@ -35,7 +36,7 @@ private class TransactionConfirmationCoordinatorBridgeToPromise {
}.cauterize()
}
func promise(account: AlphaWallet.Address, transaction: UnconfirmedTransaction, configuration: TransactionConfirmationConfiguration, source: Analytics.TransactionConfirmationSource) -> Promise<ConfirmResult> {
func promise(transaction: UnconfirmedTransaction, configuration: TransactionConfirmationConfiguration, source: Analytics.TransactionConfirmationSource) -> Promise<ConfirmResult> {
let confirmationCoordinator = TransactionConfirmationCoordinator(presentingViewController: navigationController, session: session, transaction: transaction, configuration: configuration, analyticsCoordinator: analyticsCoordinator)
confirmationCoordinator.delegate = self
@ -48,15 +49,14 @@ private class TransactionConfirmationCoordinatorBridgeToPromise {
}
extension TransactionConfirmationCoordinatorBridgeToPromise: TransactionConfirmationCoordinatorDelegate {
func didSendTransaction(_ transaction: SentTransaction, inCoordinator coordinator: TransactionConfirmationCoordinator) {
didSendTransactionClosure?(transaction)
didSendTransactionClosure = .none
}
func coordinator(_ coordinator: TransactionConfirmationCoordinator, didCompleteTransaction result: TransactionConfirmationResult) {
func didFinish(_ result: ConfirmResult, in coordinator: TransactionConfirmationCoordinator) {
coordinator.close().done { _ in
switch result {
case .confirmationResult(let value):
self.seal.fulfill(value)
case .noData:
self.seal.reject(DAppError.cancelled)
}
self.seal.fulfill(result)
}.cauterize()
}
@ -107,10 +107,10 @@ extension UIViewController {
}
extension TransactionConfirmationCoordinator {
//session contains account already
static func promise(_ navigationController: UINavigationController, session: WalletSession, coordinator: Coordinator & CanOpenURL, account: AlphaWallet.Address, transaction: UnconfirmedTransaction, configuration: TransactionConfirmationConfiguration, analyticsCoordinator: AnalyticsCoordinator, source: Analytics.TransactionConfirmationSource) -> Promise<ConfirmResult> {
let bridge = TransactionConfirmationCoordinatorBridgeToPromise(navigationController, session: session, coordinator: coordinator, analyticsCoordinator: analyticsCoordinator)
return bridge.promise(account: account, transaction: transaction, configuration: configuration, source: source)
// NOTE: Hack usage of closure `didSendTransactionClosure`, its not good to do like that,
// made to easily get called `didSendTransaction` method as promise can't be called twice
static func promise(_ navigationController: UINavigationController, session: WalletSession, coordinator: Coordinator & CanOpenURL, transaction: UnconfirmedTransaction, configuration: TransactionConfirmationConfiguration, analyticsCoordinator: AnalyticsCoordinator, source: Analytics.TransactionConfirmationSource, didSendTransactionClosure: @escaping (SentTransaction) -> Void) -> Promise<ConfirmResult> {
let bridge = TransactionConfirmationCoordinatorBridgeToPromise(navigationController, session: session, coordinator: coordinator, analyticsCoordinator: analyticsCoordinator, didSendTransactionClosure: didSendTransactionClosure)
return bridge.promise(transaction: transaction, configuration: configuration, source: source)
}
}

@ -222,13 +222,15 @@ extension WalletConnectCoordinator: WalletConnectServerDelegate {
let ethPrice = nativeCryptoCurrencyPrices[rpcServer]
let configuration: TransactionConfirmationConfiguration = .walletConnect(confirmType: type, keystore: keystore, ethPrice: ethPrice)
return firstly {
TransactionConfirmationCoordinator.promise(navigationController, session: session, coordinator: self, account: session.account.address, transaction: transaction, configuration: configuration, analyticsCoordinator: analyticsCoordinator, source: .walletConnect)
TransactionConfirmationCoordinator.promise(navigationController, session: session, coordinator: self, transaction: transaction, configuration: configuration, analyticsCoordinator: analyticsCoordinator, source: .walletConnect, didSendTransactionClosure: { [weak self] tx in
guard let strongSelf = self else { return }
strongSelf.delegate?.didSendTransaction(tx, inCoordinator: strongSelf)
})
}.map { data -> WalletConnectServer.Callback in
switch data {
case .signedTransaction(let data):
return .init(id: id, url: url, value: data)
case .sentTransaction(let transaction):
self.delegate?.didSendTransaction(transaction, inCoordinator: self)
let data = Data(_hex: transaction.id)
return .init(id: id, url: url, value: data)
case .sentRawTransaction:

Loading…
Cancel
Save