Add handling for failed transactions

pull/2/head
Michael Scoff 7 years ago
parent 9058cbae68
commit c149b2fa7d
  1. 33
      Trust/Transactions/Coordinators/TransactionDataCoordinator.swift
  2. 9
      Trust/Transactions/Storage/TransactionsStorage.swift
  3. 1
      Trust/Transactions/Types/TransactionItemState.swift
  4. 6
      Trust/Transactions/ViewModels/TransactionCellViewModel.swift
  5. 2
      Trust/Transactions/ViewModels/TransactionDetailsViewModel.swift
  6. 13
      TrustTests/Coordinators/InCoordinatorTests.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()

@ -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 {

@ -6,6 +6,7 @@ enum TransactionState: Int {
case completed
case pending
case error
case failed
case unknown
init(int: Int) {

@ -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()

@ -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

@ -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() {

Loading…
Cancel
Save