Fix again: TokenScript attribute fetching (actually most smart contract function calls) not working anymore, so TokenScript views display NaN #1652

pull/2122/head
Hwee-Boon Yar 4 years ago
parent d7be042145
commit cf817dc6b0
  1. 2
      AlphaWallet/Tokens/Helpers/CallSmartContractFunction.swift
  2. 85
      AlphaWallet/Tokens/Types/TokensDataStore.swift
  3. 27
      AlphaWallet/Tokens/ViewControllers/TokensViewController.swift
  4. 23
      AlphaWallet/Transactions/ViewControllers/TransactionsViewController.swift
  5. 4
      Podfile
  6. 8
      Podfile.lock

@ -10,7 +10,7 @@ var smartContractCallsCache = [String: (promise: Promise<[String: Any]>, timesta
func callSmartContract(withServer server: RPCServer, contract: AlphaWallet.Address, functionName: String, abiString: String, parameters: [AnyObject] = [AnyObject](), timeout: TimeInterval? = nil) -> Promise<[String: Any]> {
//We must include the ABI string in the key because the order of elements in a dictionary when serialized in the string is not ordered. Parameters (which is ordered) should ensure it's the same function
let cacheKey = "\(contract).\(functionName) \(parameters) \(server.chainID)"
let ttlForCache: TimeInterval = 3
let ttlForCache: TimeInterval = 10
let now = Date()
if let (cachedPromise, cacheTimestamp) = smartContractCallsCache[cacheKey] {
let diff = now.timeIntervalSince(cacheTimestamp)

@ -485,48 +485,57 @@ class TokensDataStore {
}
}
for tokenObject in tokens {
switch tokenObject.type {
case .nativeCryptocurrency:
incrementCountAndUpdateDelegate()
case .erc20:
getERC20Balance(for: tokenObject.contractAddress, completion: { [weak self] result in
defer { incrementCountAndUpdateDelegate() }
guard let strongSelf = self else { return }
switch result {
case .success(let balance):
strongSelf.update(token: tokenObject, action: .value(balance))
case .failure:
break
}
})
case .erc875:
getERC875Balance(for: tokenObject.contractAddress, completion: { [weak self] result in
defer { incrementCountAndUpdateDelegate() }
guard let strongSelf = self else { return }
switch result {
case .success(let balance):
strongSelf.update(token: tokenObject, action: .nonFungibleBalance(balance))
case .failure:
break
}
})
case .erc721:
break
case .erc721ForTickets:
getERC721ForTicketsBalance(for: tokenObject.contractAddress, completion: { [weak self] result in
defer { incrementCountAndUpdateDelegate() }
guard let strongSelf = self else { return }
switch result {
case .success(let balance):
strongSelf.update(token: tokenObject, action: .nonFungibleBalance(balance))
case .failure:
break
}
})
//We don't want a whole lot of RPC calls to go out at once. If the user has 100 ERC20 tokens, that's 100 `balanceOf`. iOS doesn't lke it and will return this error:
//Error Domain=NSPOSIXErrorDomain Code=28 "No space left on device" UserInfo={_kCFStreamErrorCodeKey=28, _kCFStreamErrorDomainKey=1}
let delay = TimeInterval.random(in: 0...20)
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
self.refreshBalance(forToken: tokenObject, completion: incrementCountAndUpdateDelegate)
}
}
}
private func refreshBalance(forToken tokenObject: TokenObject, completion: @escaping () -> Void) {
switch tokenObject.type {
case .nativeCryptocurrency:
completion()
case .erc20:
getERC20Balance(for: tokenObject.contractAddress, completion: { [weak self] result in
defer { completion() }
guard let strongSelf = self else { return }
switch result {
case .success(let balance):
strongSelf.update(token: tokenObject, action: .value(balance))
case .failure:
break
}
})
case .erc875:
getERC875Balance(for: tokenObject.contractAddress, completion: { [weak self] result in
defer { completion() }
guard let strongSelf = self else { return }
switch result {
case .success(let balance):
strongSelf.update(token: tokenObject, action: .nonFungibleBalance(balance))
case .failure:
break
}
})
case .erc721:
break
case .erc721ForTickets:
getERC721ForTicketsBalance(for: tokenObject.contractAddress, completion: { [weak self] result in
defer { completion() }
guard let strongSelf = self else { return }
switch result {
case .success(let balance):
strongSelf.update(token: tokenObject, action: .nonFungibleBalance(balance))
case .failure:
break
}
})
}
}
private func refreshBalanceForERC721Tokens(tokens: [TokenObject]) {
assert(!tokens.contains { !$0.isERC721AndNotForTickets })
guard OpenSea.isServerSupported(server) else { return }

@ -25,6 +25,7 @@ class TokensViewController: UIViewController {
private let assetDefinitionStore: AssetDefinitionStore
private let eventsDataStore: EventsDataStoreProtocol
private let sections: [Section] = Section.allCases
private var timeOfLastFetchBecauseViewAppears: Date?
private var viewModel: TokensViewModel {
didSet {
@ -121,7 +122,7 @@ class TokensViewController: UIViewController {
promptBackupWalletViewHolder.isHidden = newValue
adjustTableViewHeaderHeightToFitContents()
}
}
}
weak var delegate: TokensViewControllerDelegate?
//TODO The name "bad" isn't correct. Because it includes "conflicts" too
@ -212,15 +213,15 @@ class TokensViewController: UIViewController {
navigationController?.applyTintAdjustment()
navigationController?.navigationBar.prefersLargeTitles = false
hidesBottomBarWhenPushed = false
fetch()
fetchWithThrottling()
fixNavigationBarAndStatusBarBackgroundColorForiOS13Dot1()
}
@objc func pullToRefresh() {
tableViewRefreshControl.beginRefreshing()
collectiblesCollectionViewRefreshControl.beginRefreshing()
fetch()
fetchWithThrottling()
}
@objc func openConsole() {
@ -232,6 +233,24 @@ class TokensViewController: UIViewController {
tokenCollection.fetch()
}
//To reduce chance of this error occurring:
//Error Domain=NSPOSIXErrorDomain Code=28 "No space left on device" UserInfo={_kCFStreamErrorCodeKey=28, _kCFStreamErrorDomainKey=1}
private func fetchWithThrottling() {
let ttl: TimeInterval = 60 * 5
if let timeOfLastFetchBecauseViewAppears = timeOfLastFetchBecauseViewAppears {
if Date().timeIntervalSince(timeOfLastFetchBecauseViewAppears) < ttl {
//no-op
} else {
fetch()
self.timeOfLastFetchBecauseViewAppears = Date()
}
} else {
fetch()
timeOfLastFetchBecauseViewAppears = Date()
}
}
override func viewDidLayoutSubviews() {
//viewDidLayoutSubviews() is called many times
configureSearchBarOnce()

@ -16,6 +16,7 @@ class TransactionsViewController: UIViewController {
private let refreshControl = UIRefreshControl()
private let dataCoordinator: TransactionDataCoordinator
private let sessions: ServerDictionary<WalletSession>
private var timeOfLastFetchBecauseViewAppears: Date?
var paymentType: PaymentFlow?
weak var delegate: TransactionsViewControllerDelegate?
@ -74,13 +75,12 @@ class TransactionsViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
fetch()
fetchWithThrottling()
}
@objc func pullToRefresh() {
refreshControl.beginRefreshing()
fetch()
fetchWithThrottling()
}
func fetch() {
@ -93,6 +93,23 @@ class TransactionsViewController: UIViewController {
}
}
//To reduce chance of this error occurring:
//Error Domain=NSPOSIXErrorDomain Code=28 "No space left on device" UserInfo={_kCFStreamErrorCodeKey=28, _kCFStreamErrorDomainKey=1}
private func fetchWithThrottling() {
let ttl: TimeInterval = 60 * 5
if let timeOfLastFetchBecauseViewAppears = timeOfLastFetchBecauseViewAppears {
if Date().timeIntervalSince(timeOfLastFetchBecauseViewAppears) < ttl {
//no-op
} else {
fetch()
self.timeOfLastFetchBecauseViewAppears = Date()
}
} else {
fetch()
timeOfLastFetchBecauseViewAppears = Date()
}
}
func configure(viewModel: TransactionsViewModel) {
self.viewModel = viewModel
}

@ -25,7 +25,9 @@ target 'AlphaWallet' do
pod 'TrezorCrypto', :git=>'https://github.com/AlphaWallet/trezor-crypto-ios.git', :commit => '50c16ba5527e269bbc838e80aee5bac0fe304cc7'
pod 'TrustKeystore', :git => 'https://github.com/alpha-wallet/trust-keystore.git', :commit => '37f7eaf9531cb4e33d06129543b3a56972f59d2a'
pod 'SwiftyJSON'
pod 'web3swift', :git => 'https://github.com/alpha-wallet/web3swift.git', :commit => 'ae74a86c09dbec703e2aaf27217d7fb0722948ed'
#pod 'web3swift', :git => 'https://github.com/alpha-wallet/web3swift.git', :commit => 'ae74a86c09dbec703e2aaf27217d7fb0722948ed'
pod 'web3swift', :git => 'https://github.com/alpha-wallet/web3swift.git', :commit => '7e2b99198acb2243b6a539cb32832a96f67c893d'
pod 'SAMKeychain'
pod 'PromiseKit/CorePromise'
pod 'PromiseKit/Alamofire'

@ -118,7 +118,7 @@ DEPENDENCIES:
- TrezorCrypto (from `https://github.com/AlphaWallet/trezor-crypto-ios.git`, commit `50c16ba5527e269bbc838e80aee5bac0fe304cc7`)
- TrustKeystore (from `https://github.com/alpha-wallet/trust-keystore.git`, commit `37f7eaf9531cb4e33d06129543b3a56972f59d2a`)
- TrustWalletCore
- web3swift (from `https://github.com/alpha-wallet/web3swift.git`, commit `ae74a86c09dbec703e2aaf27217d7fb0722948ed`)
- web3swift (from `https://github.com/alpha-wallet/web3swift.git`, commit `7e2b99198acb2243b6a539cb32832a96f67c893d`)
SPEC REPOS:
https://github.com/CocoaPods/Specs.git:
@ -181,7 +181,7 @@ EXTERNAL SOURCES:
:commit: 37f7eaf9531cb4e33d06129543b3a56972f59d2a
:git: https://github.com/alpha-wallet/trust-keystore.git
web3swift:
:commit: ae74a86c09dbec703e2aaf27217d7fb0722948ed
:commit: 7e2b99198acb2243b6a539cb32832a96f67c893d
:git: https://github.com/alpha-wallet/web3swift.git
CHECKOUT OPTIONS:
@ -210,7 +210,7 @@ CHECKOUT OPTIONS:
:commit: 37f7eaf9531cb4e33d06129543b3a56972f59d2a
:git: https://github.com/alpha-wallet/trust-keystore.git
web3swift:
:commit: ae74a86c09dbec703e2aaf27217d7fb0722948ed
:commit: 7e2b99198acb2243b6a539cb32832a96f67c893d
:git: https://github.com/alpha-wallet/web3swift.git
SPEC CHECKSUMS:
@ -256,6 +256,6 @@ SPEC CHECKSUMS:
TrustWalletCore: dd8c81d5958f1eb737abea1e14675efcc6a104aa
web3swift: 1597d4997976d21325882db4c523f1dfd5459406
PODFILE CHECKSUM: 63c7550099e5b90c8d9ff1a91959f21dde1d9103
PODFILE CHECKSUM: ccb2db654a83c6cc6eed3f7297a37a2116d3c90d
COCOAPODS: 1.8.4

Loading…
Cancel
Save