Merge pull request #4959 from AlphaWallet/trap-print-some-promisekit-cauterized-errors

Trap and print some PromiseKit cauterized errors
pull/4960/head
Hwee-Boon Yar 2 years ago committed by GitHub
commit 5f7e489a6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      AlphaWallet/ActiveWalletCoordinator.swift
  2. 8
      AlphaWallet/Core/TokensAutodetector/AutoDetectTransactedTokensOperation.swift
  3. 38
      AlphaWallet/Core/TokensAutodetector/ImportToken.swift
  4. 5
      AlphaWallet/Core/TokensAutodetector/TokenFetcher.swift
  5. 2
      AlphaWallet/TokenScriptClient/Models/TokenScriptSignatureVerifier.swift
  6. 5
      AlphaWallet/Tokens/Logic/ContractDataDetector.swift
  7. 7
      AlphaWallet/Tokens/Logic/Erc1155TokenIdsFetcher.swift

@ -517,7 +517,9 @@ class ActiveWalletCoordinator: NSObject, Coordinator, DappRequestHandlerDelegate
importToken.importToken(for: contract, server: server, onlyIfThereIsABalance: false)
.done { _ in }
.cauterize()
.catch { error in
verboseLog("Error while adding imported token contract: \(contract.eip55String) server: \(server) wallet: \(self.wallet.address.eip55String) error: \(error)")
}
}
func show(error: Error) {

@ -15,7 +15,7 @@ protocol AutoDetectTransactedTokensOperationDelegate: class {
}
final class AutoDetectTransactedTokensOperation: Operation {
weak private var delegate: AutoDetectTransactedTokensOperationDelegate?
override var isExecuting: Bool {
return delegate?.isAutoDetectingTransactedTokens ?? false
@ -36,7 +36,7 @@ final class AutoDetectTransactedTokensOperation: Operation {
self.tokensDataStore = tokensDataStore
super.init()
self.queuePriority = session.server.networkRequestsQueuePriority
}
}
override func main() {
guard let delegate = delegate else { return }
@ -52,6 +52,8 @@ final class AutoDetectTransactedTokensOperation: Operation {
guard !strongSelf.isCancelled else { return }
strongSelf.tokensDataStore.addOrUpdate(tokensOrContracts: values)
}.cauterize()
}.catch { error in
verboseLog("Error while detecting tokens wallet: \(self.session.account.address.eip55String) error: \(error)")
}
}
}

@ -12,6 +12,8 @@ import Combine
class ImportToken {
enum ImportTokenError: Error {
case serverIsDisabled
case nothingToImport
case others
}
private let sessions: CurrentValueSubject<ServerDictionary<WalletSession>, Never>
private let assetDefinitionStore: AssetDefinitionStore
@ -34,7 +36,7 @@ class ImportToken {
private func addUefaTokenIfAny() {
guard !isRunningTests() else { return }
//NOTE: initally when we set sessions, we want to import uefa tokens, for enabled chain
sessions.filter { !$0.values.isEmpty }
.first()
@ -42,21 +44,39 @@ class ImportToken {
let server = Constants.uefaRpcServer
self.importToken(for: Constants.uefaMainnet, server: server, onlyIfThereIsABalance: true)
.done { _ in }
.cauterize()
.recover { error in
if let error = error as? ImportToken.ImportTokenError {
switch error {
case .serverIsDisabled:
//no-op. Since we didn't check if chain is enabled, we just let it be. But if there are other enum-cases, we don't want to eat the errors, we should re-throw those
break
case .nothingToImport:
//no-op. We don't import it, possibly because balance is 0
break
case .others:
throw error
}
} else {
throw error
}
}
}.store(in: &cancelable)
}
//Adding a token may fail if we lose connectivity while fetching the contract details (e.g. name and balance). So we remove the contract from the hidden list (if it was there) so that the app has the chance to add it automatically upon auto detection at startup
func importToken(for contract: AlphaWallet.Address, server: RPCServer, onlyIfThereIsABalance: Bool = false) -> Promise<Token> {
struct ImportTokenError: Error { }
return firstly {
firstly {
fetchTokenOrContract(for: contract, server: server, onlyIfThereIsABalance: onlyIfThereIsABalance)
}.map { [tokensDataStore] operation -> Token in
if let token = tokensDataStore.addOrUpdate(tokensOrContracts: [operation]).first {
return token
} else {
throw ImportTokenError()
switch operation {
case .none:
throw ImportTokenError.nothingToImport
case .ercToken, .token, .delegateContracts, .deletedContracts, .fungibleTokenComplete:
if let token = tokensDataStore.addOrUpdate(tokensOrContracts: [operation]).first {
return token
} else {
throw ImportTokenError.others
}
}
}
}

@ -37,7 +37,10 @@ class SingleChainTokenFetcher: NSObject, TokenFetcher {
case .name, .symbol, .balance, .decimals:
break
case .nonFungibleTokenComplete(let name, let symbol, let balance, let tokenType):
guard !onlyIfThereIsABalance || (onlyIfThereIsABalance && !balance.isEmpty) else { break }
guard !onlyIfThereIsABalance || (onlyIfThereIsABalance && !balance.isEmpty) else {
seal.fulfill(.none)
break
}
let token = ERCToken(
contract: contract,
server: server,

@ -39,6 +39,8 @@ class TokenScriptSignatureVerifier {
guard Features.default.isAvailable(.isTokenScriptSignatureStatusEnabled) else {
//It is safe to return without calling `completion` here since we aren't supposed to be using the results with the feature flag above
infoLog("[TokenScript] Signature verification disabled")
//We call the completion handler so that if the caller is a `Promise`, it will resolve, in order to avoid the warning: "PromiseKit: warning: pending promise deallocated"
completion(.success(domain: ""))
return
}

@ -73,19 +73,23 @@ class ContractDataDetector {
self.completionOfPartialData(.balance(balance: .erc875(balance), tokenType: .erc875))
}.catch { error in
self.nonFungibleBalanceSeal.reject(error)
self.decimalsSeal.fulfill(0)
self.callCompletionFailed()
}
case .erc721:
self.tokenProvider.getERC721Balance(for: self.address).done { balance in
self.nonFungibleBalanceSeal.fulfill(.balance(balance))
self.decimalsSeal.fulfill(0)
self.completionOfPartialData(.balance(balance: .balance(balance), tokenType: .erc721))
}.catch { error in
self.nonFungibleBalanceSeal.reject(error)
self.decimalsSeal.fulfill(0)
self.callCompletionFailed()
}
case .erc721ForTickets:
self.tokenProvider.getERC721ForTicketsBalance(for: self.address).done { balance in
self.nonFungibleBalanceSeal.fulfill(.erc721ForTickets(balance))
self.decimalsSeal.fulfill(0)
self.completionOfPartialData(.balance(balance: .erc721ForTickets(balance), tokenType: .erc721ForTickets))
}.catch { error in
self.nonFungibleBalanceSeal.reject(error)
@ -94,6 +98,7 @@ class ContractDataDetector {
case .erc1155:
let balance: [String] = .init()
self.nonFungibleBalanceSeal.fulfill(.balance(balance))
self.decimalsSeal.fulfill(0)
self.completionOfPartialData(.balance(balance: .balance(balance), tokenType: .erc1155))
case .erc20:
self.tokenProvider.getDecimals(for: self.address).done { decimal in

@ -137,6 +137,9 @@ extension Erc1155TokenIdsFetcher {
}
extension Erc1155TokenIdsFetcher.functional {
//This is only for development purposes to keep the PromiseKit `Resolver`(s) from being deallocated when they aren't resolved so PromiseKit don't show a warning and create noise and confusion
private static var fetchEventsPromiseKitResolversKeptForDevelopmentFeatureFlagOnly: [Resolver<[Erc1155TransferEvent]>] = .init()
static func fetchEvents(config: Config, forAddress address: AlphaWallet.Address, server: RPCServer, fromBlock: EventFilter.Block, toBlock: EventFilter.Block, queue: DispatchQueue) -> Promise<Erc1155TokenIds> {
let recipientAddress = EthereumAddress(address.eip55String)!
let nullFilter: [EventFilterable]? = nil
@ -177,7 +180,9 @@ extension Erc1155TokenIdsFetcher.functional {
fileprivate static func fetchEvents(config: Config, server: RPCServer, transferType: Erc1155TransferEvent.TransferType, eventName: String, parameterFilters: [[EventFilterable]?], fromBlock: EventFilter.Block, toBlock: EventFilter.Block, queue: DispatchQueue) -> Promise<[Erc1155TransferEvent]> {
if config.development.isAutoFetchingDisabled {
return Promise { _ in }
return Promise<[Erc1155TransferEvent]> { seal in
fetchEventsPromiseKitResolversKeptForDevelopmentFeatureFlagOnly.append(seal)
}
}
//We just need any contract for the Swift API to get events, it's not actually used

Loading…
Cancel
Save