mirror of
https://github.com/luxfi/safe-ios.git
synced 2026-10-30 15:19:20 +00:00
118 lines
3.4 KiB
Swift
118 lines
3.4 KiB
Swift
//
|
|
// SafeInfoLoader.swift
|
|
// Multisig
|
|
//
|
|
// Created by Dmitry Bespalov on 15.06.22.
|
|
// Copyright © 2022 Gnosis Ltd. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
// Loads safe info from the backend and Safe Account owners from the blockchain
|
|
// and combines two results so that the owners addresses are up-to-date with the
|
|
// blockchain.
|
|
class SafeInfoLoader {
|
|
|
|
private var chain: Chain!
|
|
private var address: Address!
|
|
|
|
private var tasks: [URLSessionTask?]!
|
|
|
|
private var safeInfo: SCGModels.SafeInfoExtended?
|
|
private var owners: [Address]?
|
|
|
|
private var errors: [Error]!
|
|
|
|
private var completion: (Result<SCGModels.SafeInfoExtended, Error>) -> Void = { _ in }
|
|
|
|
// if you cancel, you won't receive completion call back.
|
|
func cancel() {
|
|
for task in tasks {
|
|
task?.cancel()
|
|
}
|
|
}
|
|
|
|
// call this
|
|
func load(chain: Chain, safe: Address, completion: @escaping (Result<SCGModels.SafeInfoExtended, Error>) -> Void) {
|
|
self.chain = chain
|
|
self.address = safe
|
|
self.completion = completion
|
|
DispatchQueue.global().async { [unowned self] in
|
|
self.load()
|
|
}
|
|
}
|
|
|
|
private func load() {
|
|
assert(chain != nil)
|
|
assert(address != nil)
|
|
|
|
tasks = []
|
|
errors = []
|
|
|
|
loadSafeInfo()
|
|
}
|
|
|
|
private func handleLoadedData() {
|
|
guard errors.isEmpty else {
|
|
dispatchOnMainThread({ [unowned self] in
|
|
completion(.failure(errors.first!))
|
|
}())
|
|
return
|
|
}
|
|
|
|
guard var safeInfo = safeInfo, let owners = owners else {
|
|
// cancelled, just silently stop.
|
|
LogService.shared.debug("Safe Loading cancelled")
|
|
return
|
|
}
|
|
|
|
// substitute server response with the up-to-date blockchain data of the owners
|
|
safeInfo.owners = owners.map { address in
|
|
SCGModels.AddressInfo(value: AddressString(address))
|
|
}
|
|
|
|
dispatchOnMainThread({ [unowned self] in
|
|
completion(.success(safeInfo))
|
|
}())
|
|
}
|
|
|
|
private func loadSafeInfo() {
|
|
safeInfo = nil
|
|
let task = App.shared.clientGatewayService.asyncSafeInfo(safeAddress: address, chainId: chain.id!) { [weak self] result in
|
|
self?.handleAsyncResult(result: result, success: { info in
|
|
self?.safeInfo = info
|
|
|
|
// only if successful, load owners
|
|
self?.loadOwners()
|
|
})
|
|
}
|
|
tasks.append(task)
|
|
}
|
|
|
|
private func loadOwners() {
|
|
owners = nil
|
|
let task = SafeTransactionController.shared.getOwners(safe: address, chain: chain) { [weak self] result in
|
|
self?.handleAsyncResult(result: result, success: { addresses in
|
|
self?.owners = addresses
|
|
|
|
// on success, process results
|
|
self?.handleLoadedData()
|
|
})
|
|
}
|
|
tasks.append(task)
|
|
}
|
|
|
|
private func handleAsyncResult<R,E>(result: Result<R, E>, success: (R) -> Void) {
|
|
do {
|
|
let value = try result.get()
|
|
success(value)
|
|
} catch let nsError as NSError where nsError.code == URLError.Code.cancelled.rawValue && nsError.domain == NSURLErrorDomain {
|
|
// ignore cancellation errors
|
|
LogService.shared.debug("Cancelled URL loading")
|
|
} catch {
|
|
errors.append(GSError.detailedError(from: error))
|
|
handleLoadedData()
|
|
}
|
|
}
|
|
}
|