Skip to content

Commit 25b8105

Browse files
committed
Merge branch 'feature/stability_improvements' into develop
2 parents d7c8f83 + 87b2be4 commit 25b8105

20 files changed

+401
-185
lines changed

Kukai Mobile.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Kukai Mobile/Modules/Account/AccountViewModel.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,8 @@ class AccountViewModel: ViewModel, UITableViewDiffableDataSourceHandler {
346346
let obj = dataSource?.itemIdentifier(for: atIndexPath)
347347

348348
if obj is XTZAmount {
349-
return Token.xtz(withAmount: DependencyManager.shared.balanceService.account.xtzBalance)
349+
let account = DependencyManager.shared.balanceService.account
350+
return Token.xtz(withAmount: account.xtzBalance, stakedAmount: account.xtzStakedBalance, unstakedAmount: account.xtzUnstakedBalance)
350351

351352
} else if obj is Token {
352353
return obj as? Token

Kukai Mobile/Modules/Collectibles/CollectiblesCollectionsViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class CollectiblesCollectionsViewController: UIViewController, UICollectionViewD
2020
private var movingToDetails = false
2121
private var textFieldDone = false
2222
private var lastSearchedTerm: String? = nil
23-
private var ignoreNextTextFieldDidEnd = true
23+
private var ignoreNextTextFieldDidEnd = false
2424

2525
public weak var delegate: UIViewController? = nil
2626

Kukai Mobile/Modules/Onboarding/WelcomeViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class WelcomeViewController: UIViewController {
3030
if (UIApplication.shared.delegate as? AppDelegate)?.shouldLaunchGhostnet() == true {
3131
DependencyManager.shared.setDefaultTestnetURLs(supressUpdateNotification: true)
3232

33-
} else if DependencyManager.shared.currentNetworkType != .mainnet {
33+
} else if DependencyManager.shared.currentNetworkType != .mainnet {
3434
DependencyManager.shared.setDefaultMainnetURLs(supressUpdateNotification: true)
3535
}
3636

Kukai Mobile/Modules/Send/SendTokenAmountViewController.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@ class SendTokenAmountViewController: UIViewController {
5656

5757

5858
// Token data
59-
balanceLabel.text = token.balance.normalisedRepresentation
59+
balanceLabel.text = token.availableBalance.normalisedRepresentation
6060
symbolLabel.text = token.symbol
6161
fiatValueLabel?.text = DependencyManager.shared.balanceService.fiatAmountDisplayString(forToken: token, ofAmount: .zero())
6262
tokenIcon.addTokenIcon(token: token)
6363

6464

6565
// Textfield
6666
textfield.validatorTextFieldDelegate = self
67-
textfield.validator = TokenAmountValidator(balanceLimit: token.balance, decimalPlaces: token.decimalPlaces)
67+
textfield.validator = TokenAmountValidator(balanceLimit: token.availableBalance, decimalPlaces: token.decimalPlaces)
6868
textfield.addDoneToolbar()
6969
textfield.numericAndSeperatorOnly = true
7070

@@ -85,7 +85,7 @@ class SendTokenAmountViewController: UIViewController {
8585
}
8686

8787
@IBAction func maxButtonTapped(_ sender: UIButton) {
88-
textfield.text = selectedToken?.balance.normalisedRepresentation ?? ""
88+
textfield.text = selectedToken?.availableBalance.normalisedRepresentation ?? ""
8989
let _ = textfield.revalidateTextfield()
9090
}
9191

@@ -168,7 +168,7 @@ extension SendTokenAmountViewController: ValidatorTextFieldDelegate {
168168
}
169169

170170
func validateMaxXTZ(input: String) {
171-
if selectedToken?.isXTZ() == true, let balance = selectedToken?.balance, let inputAmount = XTZAmount(fromNormalisedAmount: input, decimalPlaces: 6), balance == inputAmount {
171+
if selectedToken?.isXTZ() == true, let balance = selectedToken?.availableBalance, let inputAmount = XTZAmount(fromNormalisedAmount: input, decimalPlaces: 6), balance == inputAmount {
172172
maxWarningLabel.isHidden = false
173173
} else {
174174
maxWarningLabel.isHidden = true

Kukai Mobile/Modules/Send/SendTokenConfirmViewController.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,8 +262,8 @@ class SendTokenConfirmViewController: SendAbstractConfirmViewController, SlideBu
262262

263263
// Sum of send amount + fee is greater than balance, need to adjust send amount
264264
// For safety, don't allow this logic coming from WC2, as its likely the user is communicating with a smart contract that likely won't accept recieving less than expected XTZ
265-
if !isWalletConnectOp, let token = currentSendData.chosenToken, token.isXTZ(), let amount = currentSendData.chosenAmount, (amount + fee) >= token.balance, let oneMutez = XTZAmount(fromRpcAmount: "1") {
266-
let updatedValue = ((token.balance - oneMutez) - fee)
265+
if !isWalletConnectOp, let token = currentSendData.chosenToken, token.isXTZ(), let amount = currentSendData.chosenAmount, (amount + fee) >= token.availableBalance, let oneMutez = XTZAmount(fromRpcAmount: "1") {
266+
let updatedValue = ((token.availableBalance - oneMutez) - fee)
267267

268268
if updatedValue < .zero() {
269269
updateAmountDisplay(withValue: .zero())
@@ -272,10 +272,10 @@ class SendTokenConfirmViewController: SendAbstractConfirmViewController, SlideBu
272272

273273
if isFirstCall {
274274
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
275-
self?.windowError(withTitle: "error-funds-title".localized(), description: String.localized("error-funds-body", withArguments: token.balance.normalisedRepresentation, fee.normalisedRepresentation))
275+
self?.windowError(withTitle: "error-funds-title".localized(), description: String.localized("error-funds-body", withArguments: token.availableBalance.normalisedRepresentation, fee.normalisedRepresentation))
276276
}
277277
} else {
278-
self.windowError(withTitle: "error-funds-title".localized(), description: String.localized("error-funds-body", withArguments: token.balance.normalisedRepresentation, fee.normalisedRepresentation))
278+
self.windowError(withTitle: "error-funds-title".localized(), description: String.localized("error-funds-body", withArguments: token.availableBalance.normalisedRepresentation, fee.normalisedRepresentation))
279279
}
280280

281281
} else {

Kukai Mobile/Modules/Stake/StakeViewController.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,19 +87,17 @@ class StakeViewController: UIViewController {
8787
}
8888

8989
self.showLoadingView()
90-
9190
let operations = OperationFactory.delegateOperation(to: toAddress, from: selectedWallet.address)
9291
DependencyManager.shared.tezosNodeClient.estimate(operations: operations, walletAddress: selectedWallet.address, base58EncodedPublicKey: selectedWallet.publicKeyBase58encoded()) { [weak self] estimationResult in
92+
self?.hideLoadingView()
9393

9494
switch estimationResult {
9595
case .success(let estimationResult):
9696
TransactionService.shared.currentOperationsAndFeesData = TransactionService.OperationsAndFeesData(estimatedOperations: estimationResult.operations)
9797
TransactionService.shared.currentForgedString = estimationResult.forgedString
98-
self?.loadingViewHideActivity()
9998
self?.performSegue(withIdentifier: "confirm", sender: nil)
10099

101100
case .failure(let estimationError):
102-
self?.hideLoadingView()
103101
self?.windowError(withTitle: "error".localized(), description: estimationError.description)
104102
}
105103
}

Kukai Mobile/Services/BalanceService.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ public class BalanceService {
192192
DependencyManager.shared.activityService.checkAndUpdatePendingTransactions(forAddress: address ?? "", comparedToGroups: DependencyManager.shared.activityService.transactionGroups)
193193

194194
self.account = account
195+
196+
} else if let add = address {
197+
// If local cache fails to parse, models must have change. Delete everything, will trigger a network refresh
198+
deleteAccountCachcedData(forAddress: add)
195199
}
196200

197201
cacheLoadingInProgress = false
@@ -271,7 +275,7 @@ public class BalanceService {
271275
// MARK: - Refresh
272276

273277
private func fetchAllBalancesTokensAndPrices(forAddress address: String, refreshType: BalanceService.RefreshType, completion: @escaping ((KukaiError?) -> Void)) {
274-
self.currentlyRefreshingAccount = Account(walletAddress: address, xtzBalance: .zero(), tokens: [], nfts: [], recentNFTs: [], liquidityTokens: [], delegate: nil, delegationLevel: nil)
278+
self.currentlyRefreshingAccount = Account(walletAddress: address, xtzBalance: .zero(), xtzStakedBalance: .zero(), xtzUnstakedBalance: .zero(), tokens: [], nfts: [], recentNFTs: [], liquidityTokens: [], delegate: nil, delegationLevel: nil)
275279

276280
var error: KukaiError? = nil
277281
balanceRequestDispathGroup.enter()
@@ -285,7 +289,7 @@ public class BalanceService {
285289
if refreshType == .useCache || (refreshType == .useCacheIfNotStale && !isCacheStale(forAddress: address)) {
286290
let cachedAccount = DiskService.read(type: Account.self, fromFileName: BalanceService.accountCacheFilename(withAddress: address))
287291

288-
self.currentlyRefreshingAccount = cachedAccount ?? Account(walletAddress: address, xtzBalance: .zero(), tokens: [], nfts: [], recentNFTs: [], liquidityTokens: [], delegate: nil, delegationLevel: nil)
292+
self.currentlyRefreshingAccount = cachedAccount ?? Account(walletAddress: address, xtzBalance: .zero(), xtzStakedBalance: .zero(), xtzUnstakedBalance: .zero(), tokens: [], nfts: [], recentNFTs: [], liquidityTokens: [], delegate: nil, delegationLevel: nil)
289293
self.balanceRequestDispathGroup.leave()
290294

291295
loadCachedExchangeDataIfNotLoaded()
@@ -536,6 +540,8 @@ public class BalanceService {
536540

537541
let newAccount = Account(walletAddress: self?.currentlyRefreshingAccount.walletAddress ?? "",
538542
xtzBalance: self?.currentlyRefreshingAccount.xtzBalance ?? .zero(),
543+
xtzStakedBalance: self?.currentlyRefreshingAccount.xtzStakedBalance ?? .zero(),
544+
xtzUnstakedBalance: self?.currentlyRefreshingAccount.xtzUnstakedBalance ?? .zero(),
539545
tokens: newTokens,
540546
nfts: newNFTs,
541547
recentNFTs: self?.currentlyRefreshingAccount.recentNFTs ?? [],

Kukai Mobile/Services/WalletConnectService.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ public class WalletConnectService {
106106
Pair.configure(metadata: WalletConnectService.metadata)
107107
Sign.configure(crypto: WC2CryptoProvider())
108108

109-
110109
// Monitor connection
111110
Networking.instance.socketConnectionStatusPublisher.sink { status in
112111
Logger.app.info("WC2 - Connection status: changed to \(status == .connected ? "connected" : "disconnected")")

Kukai MobileUITests/SharedHelpers.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ class SharedHelpers: XCTestCase {
3030
// MARK: - Helpers
3131

3232
func application(resetForEveryInvocation: Bool = false) -> XCUIApplication {
33-
sharedApplication.launchEnvironment = ["XCUITEST-KEYBOARD": "true"]
34-
sharedApplication.launchEnvironment = ["XCUITEST-GHOSTNET": "true"]
35-
sharedApplication.launchEnvironment = ["XCUITEST-STUB-XTZ-PRICE": "true"]
33+
sharedApplication.launchEnvironment["XCUITEST-KEYBOARD"] = "true"
34+
sharedApplication.launchEnvironment["XCUITEST-GHOSTNET"] = "true"
35+
sharedApplication.launchEnvironment["XCUITEST-STUB-XTZ-PRICE"] = "true"
3636

3737

3838
// When starting a new set of tests, clear all the data on the device so no lingering data from a previous failed test is present

Kukai MobileUITests/Tests/Test_02_Onboarding.swift

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ final class Test_02_Onboarding: XCTestCase {
158158
// Navigate to wallet management
159159
Test_03_Home.handleOpenWalletManagement(app: app)
160160

161+
Test_05_WalletManagement.addAccount(app: app, toWallet: testConfig.walletAddress_HD.truncateTezosAddress(), waitForNewAddress: testConfig.walletAddress_HD_account_1.truncateTezosAddress())
161162
Test_05_WalletManagement.check(app: app, hasSections: 1)
162163
Test_05_WalletManagement.check(app: app, hasWalletsOrAccounts: 2)
163164

@@ -443,6 +444,75 @@ final class Test_02_Onboarding: XCTestCase {
443444
Test_05_WalletManagement.deleteAllWallets(app: app)
444445
}
445446

447+
func testImportPrivateKey_unencrypted() {
448+
let app = XCUIApplication()
449+
app.staticTexts["Already Have a Wallet"].tap()
450+
451+
Test_02_Onboarding.handleImportPrivateKey(app: app, key: "edsk3KvXD8SVD9GCyU4jbzaFba2HZRad5pQ7ajL79n7rUoc3nfHv5t", encryptedWith: nil)
452+
453+
454+
// Confirm terms and conditions and create a passcode
455+
SharedHelpers.shared.waitForButton("checkmark", exists: true, inElement: app, delay: 5)
456+
457+
app.buttons["checkmark"].tap()
458+
app.staticTexts["Get Started"].tap()
459+
460+
// Create passcode
461+
Test_02_Onboarding.handlePasscode(app: app)
462+
Test_02_Onboarding.handlePasscode(app: app)
463+
Test_04_Account.waitForInitalLoad(app: app)
464+
465+
466+
// App state verification
467+
Test_04_Account.waitForInitalLoad(app: app)
468+
469+
470+
// Navigate to wallet management
471+
Test_03_Home.handleOpenWalletManagement(app: app)
472+
473+
Test_05_WalletManagement.check(app: app, hasSections: 1)
474+
Test_05_WalletManagement.check(app: app, hasWalletsOrAccounts: 1)
475+
476+
let details0 = Test_05_WalletManagement.getWalletDetails(app: app, index: 0)
477+
XCTAssert(details0.title == "tz1Qvps...joCH", details0.title)
478+
479+
Test_05_WalletManagement.deleteAllWallets(app: app)
480+
}
481+
482+
func testImportPrivateKey_encrypted() {
483+
let app = XCUIApplication()
484+
app.staticTexts["Already Have a Wallet"].tap()
485+
486+
Test_02_Onboarding.handleImportPrivateKey(app: app, key: "edesk1L8uVSYd3aug7jbeynzErQTnBxq6G6hJwmeue3yUBt11wp3ULXvcLwYRzDp4LWWvRFNJXRi3LaN7WGiEGhh", encryptedWith: "pa55word")
487+
488+
489+
// Confirm terms and conditions and create a passcode
490+
SharedHelpers.shared.waitForButton("checkmark", exists: true, inElement: app, delay: 5)
491+
492+
app.buttons["checkmark"].tap()
493+
app.staticTexts["Get Started"].tap()
494+
495+
// Create passcode
496+
Test_02_Onboarding.handlePasscode(app: app)
497+
Test_02_Onboarding.handlePasscode(app: app)
498+
Test_04_Account.waitForInitalLoad(app: app)
499+
500+
501+
// App state verification
502+
Test_04_Account.waitForInitalLoad(app: app)
503+
504+
505+
// Navigate to wallet management
506+
Test_03_Home.handleOpenWalletManagement(app: app)
507+
508+
Test_05_WalletManagement.check(app: app, hasSections: 1)
509+
Test_05_WalletManagement.check(app: app, hasWalletsOrAccounts: 1)
510+
511+
let details0 = Test_05_WalletManagement.getWalletDetails(app: app, index: 0)
512+
XCTAssert(details0.title == "tz1Xzte...GuMF", details0.title)
513+
514+
Test_05_WalletManagement.deleteAllWallets(app: app)
515+
}
446516

447517

448518
// MARK: - Helpers
@@ -469,6 +539,22 @@ final class Test_02_Onboarding: XCTestCase {
469539
app.buttons["send-button"].tap()
470540
}
471541

542+
public static func handleImportPrivateKey(app: XCUIApplication, key: String, encryptedWith: String?) {
543+
app.tables.staticTexts["Import a Private Key"].tap()
544+
545+
app.scrollViews.children(matching: .textView).element.tap()
546+
app.typeText(key)
547+
548+
if let pass = encryptedWith {
549+
app.textFields.firstMatch.tap()
550+
app.typeText(pass)
551+
}
552+
553+
SharedHelpers.shared.typeDone(app: app)
554+
555+
app.buttons["Import"].tap()
556+
}
557+
472558
public static func handleBasicImport(app: XCUIApplication, useAutoComplete: Bool) {
473559
let testConfig = EnvironmentVariables.shared.config()
474560
let seedPhrase = testConfig.seed
@@ -593,8 +679,14 @@ final class Test_02_Onboarding: XCTestCase {
593679
sleep(2)
594680
}
595681

596-
597682
SharedHelpers.shared.waitForButton("Don’t Merge", exists: true, inElement: settingsApp, delay: 10)
683+
684+
let notNowButton = settingsApp.buttons["Not Now"]
685+
if notNowButton.exists {
686+
notNowButton.tap()
687+
sleep(2)
688+
}
689+
598690
settingsApp.buttons["Don’t Merge"].tap()
599691

600692
SharedHelpers.shared.waitForStaticText("Sign Out", exists: true, inElement: settingsApp, delay: 30)

Kukai MobileUITests/Tests/Test_03_Home.swift

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,18 @@ final class Test_03_Home: XCTestCase {
2828

2929
func test_01_importWalletsNeeded() throws {
3030
let app = XCUIApplication()
31-
31+
let testConfig = EnvironmentVariables.shared.config()
3232

3333
// Import the HD wallet and wait for the initial load
3434
// This will be used for ghostnet to perform transactions
3535
Test_02_Onboarding.handleBasicImport(app: app, useAutoComplete: false)
36-
3736
Test_03_Home.handleOpenWalletManagement(app: app)
38-
sleep(2)
37+
Test_05_WalletManagement.addAccount(app: app, toWallet: testConfig.walletAddress_HD.truncateTezosAddress(), waitForNewAddress: testConfig.walletAddress_HD_account_1.truncateTezosAddress())
3938

4039
Test_05_WalletManagement.addMore(app: app)
4140

42-
SharedHelpers.shared.tapSecondaryButton(app: app)
43-
sleep(2)
44-
41+
app.staticTexts["Add Existing Wallet"].tap()
42+
sleep(1)
4543

4644
// Import a known mainnet wallet as a watch wallet, allowing to perform mainnet checks like baker rewards
4745
Test_02_Onboarding.handleImportWatchWallet_address(app: app, address: Test_05_WalletManagement.mainnetWatchWalletAddress)

Kukai MobileUITests/Tests/Test_04_Account.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ final class Test_04_Account: XCTestCase {
1616

1717
override func setUpWithError() throws {
1818
continueAfterFailure = true
19-
20-
SharedHelpers.shared.application().launch()
2119
}
2220

2321
override func tearDownWithError() throws {
@@ -388,7 +386,12 @@ final class Test_04_Account: XCTestCase {
388386
bakerButton.tap()
389387
sleep(2)
390388

391-
app.tables.staticTexts["Baking Benjamins"].tap()
389+
let name = "Baking Benjamins"
390+
if app.tables.staticTexts[name].exists {
391+
app.tables.staticTexts["Baking Benjamins"].tap()
392+
} else {
393+
app.tables.staticTexts["tz1YgDU...4jnD"].tap()
394+
}
392395
sleep(2)
393396

394397
SharedHelpers.shared.tapPrimaryButton(app: app)

Kukai MobileUITests/Tests/Test_05_WalletManagement.swift

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ final class Test_05_WalletManagement: XCTestCase {
1818
override func setUpWithError() throws {
1919
continueAfterFailure = false
2020

21-
SharedHelpers.shared.application().launch()
21+
XCUIApplication().launch()
2222
}
2323

2424
override func tearDownWithError() throws {
@@ -123,10 +123,10 @@ final class Test_05_WalletManagement: XCTestCase {
123123
Test_05_WalletManagement.addMore(app: app)
124124
sleep(2)
125125

126-
SharedHelpers.shared.tapPrimaryButton(app: app)
127-
sleep(2)
126+
app.staticTexts["Create a New Wallet"].tap()
127+
sleep(1)
128128

129-
SharedHelpers.shared.tapTertiaryButton(app: app)
129+
app.staticTexts["HD Wallet"].tap()
130130
sleep(2)
131131

132132
let count = app.tables.cells.containing(.staticText, identifier: "accounts-section-header").count
@@ -150,7 +150,6 @@ final class Test_05_WalletManagement: XCTestCase {
150150

151151

152152

153-
154153
// MARK: - Helpers
155154

156155
public static func check(app: XCUIApplication, hasSections: Int) {
@@ -165,6 +164,17 @@ final class Test_05_WalletManagement: XCTestCase {
165164
XCTAssert(count == hasWalletsOrAccounts, "\(count) != \(hasWalletsOrAccounts)")
166165
}
167166

167+
public static func addAccount(app: XCUIApplication, toWallet: String, waitForNewAddress: String) {
168+
app.navigationBars.buttons["accounts-nav-add"].tap()
169+
sleep(1)
170+
171+
app.staticTexts["Add account to existing wallet"].tap()
172+
sleep(1)
173+
174+
app.staticTexts[toWallet].tap()
175+
SharedHelpers.shared.waitForStaticText(waitForNewAddress, exists: true, inElement: app, delay: 3)
176+
}
177+
168178
public static func check(app: XCUIApplication, isInEditMode: Bool) {
169179
SharedHelpers.shared.waitForImage("accounts-item-chevron", exists: isInEditMode, inElement: app.tables, delay: 1)
170180

0 commit comments

Comments
 (0)