diff --git a/Trust/Transactions/Coordinators/TransactionDataCoordinator.swift b/Trust/Transactions/Coordinators/TransactionDataCoordinator.swift index 8f6445d48..add01a7af 100644 --- a/Trust/Transactions/Coordinators/TransactionDataCoordinator.swift +++ b/Trust/Transactions/Coordinators/TransactionDataCoordinator.swift @@ -19,6 +19,11 @@ protocol TransactionDataCoordinatorDelegate: class { class TransactionDataCoordinator { + struct Config { + static let deleteMissingInternalSeconds: Double = 60.0 + static let deleyedTransactionInternalSeconds: Double = 60.0 + } + let storage: TransactionsStorage let session: WalletSession let config = Config() @@ -41,8 +46,12 @@ class TransactionDataCoordinator { } func start() { - timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(fetchPending), userInfo: nil, repeats: true) - updateTransactionsTimer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(fetchTransactions), userInfo: nil, repeats: true) + timer = Timer.scheduledTimer(timeInterval: 1, target: BlockOperation { + self.fetchPending() + }, selector: #selector(Operation.main), userInfo: nil, repeats: true) + updateTransactionsTimer = Timer.scheduledTimer(timeInterval: 1, target: BlockOperation { + self.fetchTransactions() + }, selector: #selector(Operation.main), userInfo: nil, repeats: true) } func fetch() { @@ -87,19 +96,26 @@ class TransactionDataCoordinator { Session.send(EtherServiceRequest(batch: BatchFactory().create(request))) { [weak self] result in guard let `self` = self else { return } switch result { - case .success(let transaction): - self.update(items: [transaction]) + case .success(let parsedTransaction): + NSLog("parsedTransaction \(parsedTransaction)") + if transaction.date > Date().addingTimeInterval(Config.deleyedTransactionInternalSeconds) { + self.update(state: .completed, for: transaction) + self.update(items: [transaction]) + } case .failure(let error): + // NSLog("error: \(error)") switch error { case .responseError(let error): // TODO: Think about the logic to handle pending transactions. guard let error = error as? JSONRPCError else { return } switch error { case .responseError(let code, let message, _): - NSLog("code: \(code), message \(message)") + NSLog("code \(code), error: \(message)") self.delete(transactions: [transaction]) case .resultObjectParseError: - self.delete(transactions: [transaction]) + if transaction.date < Date().addingTimeInterval(Config.deleteMissingInternalSeconds) { + self.update(state: .failed, for: transaction) + } default: break } default: break @@ -138,6 +154,11 @@ class TransactionDataCoordinator { handleUpdateItems() } + func update(state: TransactionState, for transaction: Transaction) { + storage.update(state: state, for: transaction) + handleUpdateItems() + } + func delete(transactions: [Transaction]) { storage.delete(transactions) handleUpdateItems() diff --git a/Trust/Transactions/Storage/TransactionsStorage.swift b/Trust/Transactions/Storage/TransactionsStorage.swift index 43749bbc2..694f290e8 100644 --- a/Trust/Transactions/Storage/TransactionsStorage.swift +++ b/Trust/Transactions/Storage/TransactionsStorage.swift @@ -20,6 +20,7 @@ class TransactionsStorage { var objects: [Transaction] { return realm.objects(Transaction.self) .sorted(byKeyPath: "date", ascending: false) + .filter { !$0.id.isEmpty } } var completedObjects: [Transaction] { @@ -48,6 +49,14 @@ class TransactionsStorage { } } + @discardableResult + func update(state: TransactionState, for transaction: Transaction) -> Transaction { + realm.beginWrite() + transaction.internalState = state.rawValue + try! realm.commitWrite() + return transaction + } + func deleteAll() { let objects = realm.objects(Transaction.self) try! realm.write { diff --git a/Trust/Transactions/Types/TransactionItemState.swift b/Trust/Transactions/Types/TransactionItemState.swift index 658034840..953ba8df1 100644 --- a/Trust/Transactions/Types/TransactionItemState.swift +++ b/Trust/Transactions/Types/TransactionItemState.swift @@ -6,6 +6,7 @@ enum TransactionState: Int { case completed case pending case error + case failed case unknown init(int: Int) { diff --git a/Trust/Transactions/ViewModels/TransactionCellViewModel.swift b/Trust/Transactions/ViewModels/TransactionCellViewModel.swift index c1ed66aa9..e3f6888bf 100644 --- a/Trust/Transactions/ViewModels/TransactionCellViewModel.swift +++ b/Trust/Transactions/ViewModels/TransactionCellViewModel.swift @@ -65,6 +65,8 @@ struct TransactionCellViewModel { } case .error: return NSLocalizedString("transaction.cell.error.title", value: "Error", comment: "") + case .failed: + return NSLocalizedString("transaction.cell.failed.title", value: "Failed", comment: "") case .unknown: return NSLocalizedString("transaction.cell.unknown.title", value: "Unknown", comment: "") case .pending: @@ -91,7 +93,7 @@ struct TransactionCellViewModel { switch transaction.state { case .completed: return .white - case .error, .unknown: + case .error, .unknown, .failed: return Colors.veryLightRed case .pending: return Colors.veryLightOrange @@ -112,7 +114,7 @@ struct TransactionCellViewModel { var statusImage: UIImage? { switch transaction.state { - case .error, .unknown: return R.image.transaction_error() + case .error, .unknown, .failed: return R.image.transaction_error() case .completed: switch transactionViewModel.direction { case .incoming: return R.image.transaction_received() diff --git a/Trust/Transactions/ViewModels/TransactionDetailsViewModel.swift b/Trust/Transactions/ViewModels/TransactionDetailsViewModel.swift index f1a8cb109..cf02512fa 100644 --- a/Trust/Transactions/ViewModels/TransactionDetailsViewModel.swift +++ b/Trust/Transactions/ViewModels/TransactionDetailsViewModel.swift @@ -87,7 +87,7 @@ struct TransactionDetailsViewModel { let gasFee: BigInt = { switch transaction.state { case .completed, .error: return gasPrice * gasUsed - case .pending, .unknown: return gasPrice * gasLimit + case .pending, .unknown, .failed: return gasPrice * gasLimit } }() return fullFormatter.string(from: gasFee) + " " + config.server.symbol diff --git a/TrustTests/Coordinators/InCoordinatorTests.swift b/TrustTests/Coordinators/InCoordinatorTests.swift index 5accf72b0..ef4ddb1ba 100644 --- a/TrustTests/Coordinators/InCoordinatorTests.swift +++ b/TrustTests/Coordinators/InCoordinatorTests.swift @@ -20,16 +20,9 @@ class InCoordinatorTests: XCTestCase { XCTAssertNotNil(tabbarController) - if isDebug { - XCTAssert((tabbarController?.viewControllers?[0] as? UINavigationController)?.viewControllers[0] is BrowserViewController) - XCTAssert((tabbarController?.viewControllers?[1] as? UINavigationController)?.viewControllers[0] is TransactionsViewController) - XCTAssert((tabbarController?.viewControllers?[2] as? UINavigationController)?.viewControllers[0] is TokensViewController) - XCTAssert((tabbarController?.viewControllers?[3] as? UINavigationController)?.viewControllers[0] is SettingsViewController) - } else { - XCTAssert((tabbarController?.viewControllers?[0] as? UINavigationController)?.viewControllers[0] is TransactionsViewController) - XCTAssert((tabbarController?.viewControllers?[1] as? UINavigationController)?.viewControllers[0] is TokensViewController) - XCTAssert((tabbarController?.viewControllers?[2] as? UINavigationController)?.viewControllers[0] is SettingsViewController) - } + XCTAssert((tabbarController?.viewControllers?[0] as? UINavigationController)?.viewControllers[0] is TransactionsViewController) + XCTAssert((tabbarController?.viewControllers?[1] as? UINavigationController)?.viewControllers[0] is TokensViewController) + XCTAssert((tabbarController?.viewControllers?[2] as? UINavigationController)?.viewControllers[0] is SettingsViewController) } func testChangeRecentlyUsedAccount() {