From 1f9cb7c577f36497276bc53a92f2257d7f9f3b82 Mon Sep 17 00:00:00 2001 From: Alexander Cyon Date: Wed, 12 Jun 2019 21:11:17 +0200 Subject: [PATCH] updating to bech32 --- Podfile | 5 +- Podfile.lock | 42 ++++++++--------- .../Settings.bundle/Acknowledgements.plist | 18 ------- .../Generated/SwiftGen/L10n-Constants.swift | 6 +-- .../Validators/AddressValidator.swift | 47 ++++++++++++++----- .../Localization/en.lproj/Localizable.strings | 6 ++- .../Foundation/CharacterSet_Hexadecimal.swift | 14 ++++++ .../FloatingLabelTextField+Styling.swift | 6 +-- Source/Models/TransactionIntent.swift | 27 ++++++----- Source/Models/Wallet.swift | 8 +++- .../1_Main/1_Main/0_Main/MainViewModel.swift | 2 +- .../PrepareTransactionView.swift | 4 +- .../PrepareTransactionViewModel.swift | 8 ++-- .../1_Main/A_Send/SendCoordinator.swift | 4 +- .../B_Receive/Receive/ReceiveViewModel.swift | 4 +- .../0_Settings/SettingsViewModel.swift | 4 +- .../DefaultTransactionsUseCase.swift | 2 +- .../DefaultUseCaseProvider.swift | 7 +-- Source/UseCases/TransactionsUseCase.swift | 2 +- .../Views/Delegates/TextFieldDelegate.swift | 20 ++++---- .../FloatingLabelTextField+TypeOfInput.swift | 8 +++- 21 files changed, 143 insertions(+), 101 deletions(-) diff --git a/Podfile b/Podfile index bce93a10..5a07c19e 100644 --- a/Podfile +++ b/Podfile @@ -4,14 +4,15 @@ use_modular_headers! def shared # The Zilliqa Swift SDK - pod 'Zesame', '~> 1.0.0' - pod 'BigInt', :git => 'https://github.com/attaswift/BigInt.git', :branch => 'master' + pod 'Zesame', :git => 'https://github.com/OpenZesame/Zesame.git', :branch => 'bech32' # Used for Crash reporting pod 'Firebase/Core' pod 'Fabric', '~> 1.9.0' pod 'Crashlytics', '~> 3.12.0' + pod 'SwiftProtobuf', '1.5.0' + # RxSwift made this app pod 'RxCocoa' diff --git a/Podfile.lock b/Podfile.lock index dbef2b55..1fec93ff 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - Alamofire (5.0.0-beta.5) + - Alamofire (5.0.0-beta.6) - BigInt (4.0.0) - Crashlytics (3.12.0): - Fabric (~> 1.9.0) @@ -75,8 +75,7 @@ PODS: - Differentiator (~> 3.0) - RxCocoa (~> 4.0) - RxSwift (~> 4.0) - - RxSwift (4.4.1): - - RxAtomic (~> 4.4) + - RxSwift (4.5.0) - RxTest (4.4.1): - RxAtomic (~> 4.4) - RxSwift (~> 4.0) @@ -84,19 +83,19 @@ PODS: - swift_qrcodejs (1.0.1) - SwiftGen (6.1.0) - SwiftLint (0.31.0) - - SwiftProtobuf (1.4.0) + - SwiftProtobuf (1.5.0) - SwiftyBeaver (1.6.2) - TinyConstraints (3.3.1) - Validator (3.1.1) - Zesame (1.0.0): - - Alamofire (~> 5.0.0-beta.3) + - Alamofire (~> 5.0.0-beta.4) + - BigInt (~> 4.0.0) - CryptoSwift (~> 1.0.0) - EllipticCurveKit (~> 1.0.0) - - RxSwift - - SwiftProtobuf + - RxSwift (~> 4.5.0) + - SwiftProtobuf (~> 1.5.0) DEPENDENCIES: - - BigInt (from `https://github.com/attaswift/BigInt.git`, branch `master`) - Crashlytics (~> 3.12.0) - DateToolsSwift - EFQRCode @@ -113,14 +112,16 @@ DEPENDENCIES: - SkyFloatingLabelTextField - SwiftGen - SwiftLint + - SwiftProtobuf (= 1.5.0) - SwiftyBeaver - TinyConstraints - Validator - - Zesame (~> 1.0.0) + - Zesame (from `https://github.com/OpenZesame/Zesame.git`, branch `bech32`) SPEC REPOS: https://github.com/cocoapods/specs.git: - Alamofire + - BigInt - Crashlytics - CryptoSwift - DateToolsSwift @@ -153,20 +154,19 @@ SPEC REPOS: - SwiftyBeaver - TinyConstraints - Validator - - Zesame EXTERNAL SOURCES: - BigInt: - :branch: master - :git: https://github.com/attaswift/BigInt.git + Zesame: + :branch: bech32 + :git: https://github.com/OpenZesame/Zesame.git CHECKOUT OPTIONS: - BigInt: - :commit: 108801d539eb014469c758bc0d7f734690791fb4 - :git: https://github.com/attaswift/BigInt.git + Zesame: + :commit: 2cc80066fbd3b0346269ddfa66defc597968ff06 + :git: https://github.com/OpenZesame/Zesame.git SPEC CHECKSUMS: - Alamofire: 9afb08f7f43efcc71c072374e720fcf67521317d + Alamofire: cd08a4402bd12cacd0c66f23fb12fec8d6b965e4 BigInt: 2aad1a9942dc932ec8b84290d2c564a3d76f97ab Crashlytics: 07fb167b1694128c1c9a5a5cc319b0e9c3ca0933 CryptoSwift: d81eeaa59dc5a8d03720fe919a6fd07b51f7439f @@ -190,18 +190,18 @@ SPEC CHECKSUMS: RxBlocking: 5508e90d36ca2304632dc9378ece4e9b5d4bf656 RxCocoa: 2f35a76bf8887872e28a1914112395b11b8e0e64 RxDataSources: a843bad90c29817f5923ec8163f4af2de084ceb3 - RxSwift: 92fcf68dfef21f3e2ab1965363d9e7b3d787597e + RxSwift: f172070dfd1a93d70a9ab97a5a01166206e1c575 RxTest: f8e548755ca3c7502dc41c7d3b28802c90115a38 SkyFloatingLabelTextField: 38164979b79512f9ff9288ad8acfc4bbf5d843e3 swift_qrcodejs: c181fe5c849d30c699546a23762d7e3dd143ab37 SwiftGen: f872ca75cbd17bf7103c17f13dcfa0d9a15667b0 SwiftLint: 7a0227733d786395817373b2d0ca799fd0093ff3 - SwiftProtobuf: b06646ed6cdcfc3fecd074c6000fe0c413140e4f + SwiftProtobuf: 241400280f912735c1e1b9fe675fdd2c6c4d42e2 SwiftyBeaver: 8e67ab3cd94389cbbb7a9c7cc02748d98bfee68e TinyConstraints: dbf7519aefc01ea59d62244300c7718aec68e280 Validator: b34ab17a8fffd0c1ffd8f9002ead4d1e02cd9e6e - Zesame: b30550211eb93a2626483400f0e8e24439388411 + Zesame: c7bbd6548ef648af5480338f37a94bd4fe0bc4e3 -PODFILE CHECKSUM: 7d8b08bb7466142c47bc91d4be4b4cce5728f114 +PODFILE CHECKSUM: 6e65ec8728ce77747f9fc47866b42ac7c7bfa1f6 COCOAPODS: 1.6.1 diff --git a/Source/Application/Assets/Settings.bundle/Acknowledgements.plist b/Source/Application/Assets/Settings.bundle/Acknowledgements.plist index bf80fbc8..094b3608 100644 --- a/Source/Application/Assets/Settings.bundle/Acknowledgements.plist +++ b/Source/Application/Assets/Settings.bundle/Acknowledgements.plist @@ -995,24 +995,6 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - License - MIT - Title - RxAtomic - Type - PSGroupSpecifier - - - FooterText - **The MIT License** -**Copyright © 2015 Krunoslav Zaher** -**All rights reserved.** - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. License MIT diff --git a/Source/Application/Generated/SwiftGen/L10n-Constants.swift b/Source/Application/Generated/SwiftGen/L10n-Constants.swift index 80fc2f76..6dcda7f0 100644 --- a/Source/Application/Generated/SwiftGen/L10n-Constants.swift +++ b/Source/Application/Generated/SwiftGen/L10n-Constants.swift @@ -15,10 +15,10 @@ internal enum L10n { internal enum Error { internal enum Input { internal enum Address { - /// This address isn't checksummed, yet can still be valid. + /// Invalid checksum. internal static let addressNotChecksummed = L10n.tr("Localizable", "Error.Input.Address.AddressNotChecksummed") - /// Only 0-9 and A-F allowed - internal static let containsNonHexadecimal = L10n.tr("Localizable", "Error.Input.Address.ContainsNonHexadecimal") + /// Invalid address + internal static let invalid = L10n.tr("Localizable", "Error.Input.Address.Invalid") /// Address is too long, should be %d internal static func tooLong(_ p1: Int) -> String { return L10n.tr("Localizable", "Error.Input.Address.TooLong", p1) diff --git a/Source/Application/InputValidators/Validators/AddressValidator.swift b/Source/Application/InputValidators/Validators/AddressValidator.swift index 56d4cc68..eb776a27 100644 --- a/Source/Application/InputValidators/Validators/AddressValidator.swift +++ b/Source/Application/InputValidators/Validators/AddressValidator.swift @@ -27,32 +27,55 @@ import Zesame struct AddressValidator: InputValidator { typealias Input = String typealias Output = Address - typealias Error = Address.Error +// typealias Error = Address.Error func validate(input: Input) -> Validation { do { let address = try Address(string: input) - if address.isChecksummed { - return .valid(address) - } else { - return .valid(address, remark: Error.notChecksummed) - } + return .valid(address) } catch let addressError as Address.Error { - return .invalid(.error(addressError)) + let mappedError = Error(fromAddressError: addressError) + return .invalid(.error(mappedError)) } catch { incorrectImplementation("Address.Error should cover all errors") } } + +} + +extension AddressValidator { + enum Error: InputError { + case incorrectLength(expectedLength: Int, butGot: Int) + case notChecksummed + case noBech32NorHexstring + } } -extension Address.Error: InputError { - public var errorMessage: String { +extension AddressValidator.Error { + init(fromAddressError: Zesame.Address.Error) { + switch fromAddressError { + case .incorrectLength(let expected, _, let butGot): self = .incorrectLength(expectedLength: expected, butGot: butGot) + case .notChecksummed: self = .notChecksummed + case .bech32DataEmpty, .notHexadecimal: self = .noBech32NorHexstring + case .invalidBech32Address(let bechError): + switch bechError { + case .checksumMismatch: self = .notChecksummed + default: self = .noBech32NorHexstring + } + } + } + + var errorMessage: String { let Message = L10n.Error.Input.Address.self switch self { - case .notHexadecimal: return Message.containsNonHexadecimal - case .tooLong: return Message.tooLong(Address.lengthOfValidAddresses) - case .tooShort: return Message.tooShort(Address.lengthOfValidAddresses) + case .noBech32NorHexstring: return Message.invalid + case .incorrectLength(let expected, let incorrect): + if incorrect > expected { + return Message.tooLong(expected) + } else { + return Message.tooShort(expected) + } case .notChecksummed: return Message.addressNotChecksummed } } diff --git a/Source/Application/Localization/en.lproj/Localizable.strings b/Source/Application/Localization/en.lproj/Localizable.strings index c84e5fc5..31627ba8 100644 --- a/Source/Application/Localization/en.lproj/Localizable.strings +++ b/Source/Application/Localization/en.lproj/Localizable.strings @@ -9,10 +9,12 @@ "Generic.Show" = "Show"; "Generic.Hide" = "Hide"; -"Error.Input.Address.ContainsNonHexadecimal" = "Only 0-9 and A-F allowed"; +//"Error.Input.Address.ContainsNonHexadecimal" = "Only 0-9 and A-F allowed"; + +"Error.Input.Address.Invalid" = "Invalid address"; "Error.Input.Address.TooShort" = "Address is too short, should be %d"; "Error.Input.Address.TooLong" = "Address is too long, should be %d"; -"Error.Input.Address.AddressNotChecksummed" = "This address isn't checksummed, yet can still be valid."; +"Error.Input.Address.AddressNotChecksummed" = "Invalid checksum."; "Error.Input.Amount.NonNumericString" = "String not a number"; "Error.Input.Amount.TooSmall" = "Must be at least %@"; diff --git a/Source/Extensions/Foundation/CharacterSet_Hexadecimal.swift b/Source/Extensions/Foundation/CharacterSet_Hexadecimal.swift index d180f167..91151c2b 100644 --- a/Source/Extensions/Foundation/CharacterSet_Hexadecimal.swift +++ b/Source/Extensions/Foundation/CharacterSet_Hexadecimal.swift @@ -23,10 +23,24 @@ // import Foundation +import Zesame extension CharacterSet { static var hexadecimalDigits: CharacterSet { let afToAF = CharacterSet(charactersIn: "abcdefABCDEF") return CharacterSet.decimalDigits.union(afToAF) } + + static var bech32: CharacterSet { + + let lowercase = Zesame.Bech32.alphabetString.lowercased() + let uppercase = Zesame.Bech32.alphabetString.uppercased() + + return CharacterSet(charactersIn: lowercase).union(CharacterSet(charactersIn: uppercase)) + } + + static var bech32OrHex: CharacterSet { + return CharacterSet.bech32.union(hexadecimalDigits) + } + } diff --git a/Source/Extensions/UIKit/Views+Styleable/Styling/FloatingLabelTextField+Styling.swift b/Source/Extensions/UIKit/Views+Styleable/Styling/FloatingLabelTextField+Styling.swift index 5be21f33..32b3a2aa 100644 --- a/Source/Extensions/UIKit/Views+Styleable/Styling/FloatingLabelTextField+Styling.swift +++ b/Source/Extensions/UIKit/Views+Styleable/Styling/FloatingLabelTextField+Styling.swift @@ -92,15 +92,15 @@ extension FloatingLabelTextField.Style { ) } - static var address: FloatingLabelTextField.Style { + static var addressBech32OrHex: FloatingLabelTextField.Style { return FloatingLabelTextField.Style( - typeOfInput: .hexadecimal + typeOfInput: .bech32OrHex ) } static var password: FloatingLabelTextField.Style { return FloatingLabelTextField.Style( - typeOfInput: .text, + typeOfInput: .password, isSecureTextEntry: true ) } diff --git a/Source/Models/TransactionIntent.swift b/Source/Models/TransactionIntent.swift index dce3a2fa..78cadb0a 100644 --- a/Source/Models/TransactionIntent.swift +++ b/Source/Models/TransactionIntent.swift @@ -26,19 +26,24 @@ import Foundation import Zesame struct TransactionIntent: Codable { - let to: AddressChecksummed + let to: LegacyAddress let amount: ZilAmount? - - init(to recipient: AddressChecksummedConvertible, amount: ZilAmount? = nil) { - self.to = recipient.checksummedAddress + + init(to recipient: LegacyAddress, amount: ZilAmount? = nil) { + self.to = recipient self.amount = amount } + + init(to address: Address, amount: ZilAmount? = nil) throws { + let recipient = try address.toChecksummedLegacyAddress() + self.init(to: recipient, amount: amount) + } } extension TransactionIntent { static func fromScannedQrCodeString(_ scannedString: String) -> TransactionIntent? { - if let adddress = try? AddressNotNecessarilyChecksummed(string: scannedString) { - return TransactionIntent(to: adddress) + if let address = try? Address(string: scannedString) { + return try? TransactionIntent(to: address) } else { guard let json = scannedString.data(using: .utf8), @@ -51,17 +56,17 @@ extension TransactionIntent { } extension TransactionIntent { - init?(to addresssHex: String, amount: String?) { - guard let recipient = try? AddressChecksummed(string: addresssHex) else { return nil } - self.init(to: recipient, amount: ZilAmount.fromQa(optionalString: amount)) + init?(to recipientString: String, amount: String?) { + guard let recipient = try? Address(string: recipientString) else { return nil } + try? self.init(to: recipient, amount: ZilAmount.fromQa(optionalString: amount)) } init?(queryParameters params: [URLQueryItem]) { - guard let hexAddress = params.first(where: { $0.name == TransactionIntent.CodingKeys.to.stringValue })?.value else { + guard let addressFromParam = params.first(where: { $0.name == TransactionIntent.CodingKeys.to.stringValue })?.value else { return nil } let amount = params.first(where: { $0.name == TransactionIntent.CodingKeys.amount.stringValue })?.value - self.init(to: hexAddress, amount: amount) + self.init(to: addressFromParam, amount: amount) } var queryItems: [URLQueryItem] { diff --git a/Source/Models/Wallet.swift b/Source/Models/Wallet.swift index 9b2df167..f029f6e5 100644 --- a/Source/Models/Wallet.swift +++ b/Source/Models/Wallet.swift @@ -50,7 +50,13 @@ extension Wallet { return wallet.keystore } - var address: AddressChecksummed { + var bech32Address: Bech32Address { + do { + return try Bech32Address(ethStyleAddress: wallet.address, network: network) + } catch { incorrectImplementation("should work") } + } + + var legacyAddress: LegacyAddress { return wallet.address } } diff --git a/Source/Scenes/1_Main/1_Main/0_Main/MainViewModel.swift b/Source/Scenes/1_Main/1_Main/0_Main/MainViewModel.swift index d1857059..c8429b6a 100644 --- a/Source/Scenes/1_Main/1_Main/0_Main/MainViewModel.swift +++ b/Source/Scenes/1_Main/1_Main/0_Main/MainViewModel.swift @@ -70,7 +70,7 @@ final class MainViewModel: BaseViewModel< let latestBalanceAndNonce: Driver = fetchTrigger.withLatestFrom(wallet).flatMapLatest { [unowned self] in self.transactionUseCase - .getBalance(for: $0.address) + .getBalance(for: $0.legacyAddress) .trackActivity(activityIndicator) .asDriverOnErrorReturnEmpty() .do(onNext: { [unowned self] in self.transactionUseCase.cacheBalance($0.balance) }) diff --git a/Source/Scenes/1_Main/1_Main/A_Send/1_PrepareTransaction/0_PrepareTransaction/PrepareTransactionView.swift b/Source/Scenes/1_Main/1_Main/A_Send/1_PrepareTransaction/0_PrepareTransaction/PrepareTransactionView.swift index cb11030e..a3b81ecb 100644 --- a/Source/Scenes/1_Main/1_Main/A_Send/1_PrepareTransaction/0_PrepareTransaction/PrepareTransactionView.swift +++ b/Source/Scenes/1_Main/1_Main/A_Send/1_PrepareTransaction/0_PrepareTransaction/PrepareTransactionView.swift @@ -118,7 +118,7 @@ private extension PrepareTransactionView { balanceLabels.withStyle(.horizontal) - recipientAddressField.withStyle(.address) { + recipientAddressField.withStyle(.addressBech32OrHex) { $0.placeholder(€.Field.recipient) } @@ -150,7 +150,7 @@ private extension PrepareTransactionView { private extension PrepareTransactionView { func prefillValuesForDebugBuilds() { #if DEBUG - recipientAddressField.text = "89a810e6dB25912028f704b4947a6dCF724139Ae" + recipientAddressField.text = "zil175grxdeqchwnc0qghj8qsh5vnqwww353msqj82" amountToSendField.text = Int.random(in: 100...500).description gasPriceField.text = Int.random(in: 1000...2000).description diff --git a/Source/Scenes/1_Main/1_Main/A_Send/1_PrepareTransaction/0_PrepareTransaction/PrepareTransactionViewModel.swift b/Source/Scenes/1_Main/1_Main/A_Send/1_PrepareTransaction/0_PrepareTransaction/PrepareTransactionViewModel.swift index 97f7204e..aab8a26b 100644 --- a/Source/Scenes/1_Main/1_Main/A_Send/1_PrepareTransaction/0_PrepareTransaction/PrepareTransactionViewModel.swift +++ b/Source/Scenes/1_Main/1_Main/A_Send/1_PrepareTransaction/0_PrepareTransaction/PrepareTransactionViewModel.swift @@ -70,7 +70,7 @@ final class PrepareTransactionViewModel: BaseViewModel< // Fetch latest balance from API let latestBalanceAndNonce: Driver = fetchTrigger.withLatestFrom(wallet).flatMapLatest { self.transactionUseCase - .getBalance(for: $0.address) + .getBalance(for: $0.legacyAddress) .trackActivity(activityIndicator) .trackError(errorTracker) .asDriverOnErrorReturnEmpty() @@ -89,7 +89,7 @@ final class PrepareTransactionViewModel: BaseViewModel< // MARK: Recipient Input -> Value + Validation let recipientValidationValue: Driver> = Driver.merge( input.fromView.recepientAddress.map { validator.validateRecipient($0) }, - scannedOrDeeplinkedTransaction.map { .valid(Address.checksummed($0.to)) } + scannedOrDeeplinkedTransaction.map { .valid(Address.legacy($0.to)) } ) let recipient: Driver = recipientValidationValue.map { $0.value } @@ -169,7 +169,7 @@ final class PrepareTransactionViewModel: BaseViewModel< ) let payment: Driver = Driver.combineLatest(recipient, amountBoundByBalance, gasPrice, nonce) { - guard let to = $0, let amount = $1, let price = $2, case let nonce = $3 else { + guard let to = try? $0?.toChecksummedLegacyAddress(), let amount = $1, let price = $2, case let nonce = $3 else { return nil } return Payment(to: to, amount: amount, gasLimit: 1, gasPrice: price, nonce: nonce) @@ -196,7 +196,7 @@ final class PrepareTransactionViewModel: BaseViewModel< // It is deliberate that we do NOT auto checksum the address here. We would like to be able to inform the user that // she might have pasted an unchecksummed address. - let recipientFormatted = recipient.filterNil().map { $0.hexString.value } + let recipientFormatted = recipient.filterNil().map { $0.asString } let amountFormatted = amountBoundByBalance.filterNil().map { formatter.format(amount: $0, in: .zil) } diff --git a/Source/Scenes/1_Main/1_Main/A_Send/SendCoordinator.swift b/Source/Scenes/1_Main/1_Main/A_Send/SendCoordinator.swift index a701fe70..dac3bd7c 100644 --- a/Source/Scenes/1_Main/1_Main/A_Send/SendCoordinator.swift +++ b/Source/Scenes/1_Main/1_Main/A_Send/SendCoordinator.swift @@ -143,8 +143,8 @@ private extension SendCoordinator { } func openInBrowserDetailsForTransaction(id transactionId: String) { - let baseURL = "https://explorer.zilliqa.com/" - let urlString = "transactions/\(transactionId)" + let baseURL = "https://viewblock.io/zilliqa/" + let urlString = "tx/\(transactionId)" guard let url = URL(string: urlString, relativeTo: URL(string: baseURL)) else { return } diff --git a/Source/Scenes/1_Main/1_Main/B_Receive/Receive/ReceiveViewModel.swift b/Source/Scenes/1_Main/1_Main/B_Receive/Receive/ReceiveViewModel.swift index afaa28fd..3e362c6c 100644 --- a/Source/Scenes/1_Main/1_Main/B_Receive/Receive/ReceiveViewModel.swift +++ b/Source/Scenes/1_Main/1_Main/B_Receive/Receive/ReceiveViewModel.swift @@ -73,7 +73,7 @@ final class ReceiveViewModel: BaseViewModel< ) let transactionToReceive = Driver.combineLatest( - wallet.map { $0.address }, + wallet.map { $0.legacyAddress }, amount.filterNil() ) { TransactionIntent(to: $0, amount: $1) } @@ -81,7 +81,7 @@ final class ReceiveViewModel: BaseViewModel< qrCoder.encode(transaction: $0, size: input.fromView.qrCodeImageHeight) } - let receivingAddress = wallet.map { $0.address.checksummedAddress.asString } + let receivingAddress = wallet.map { $0.bech32Address.asString } bag <~ [ input.fromController.rightBarButtonTrigger diff --git a/Source/Scenes/1_Main/1_Main/C_Settings/0_Settings/SettingsViewModel.swift b/Source/Scenes/1_Main/1_Main/C_Settings/0_Settings/SettingsViewModel.swift index ef575d16..4cc55bde 100644 --- a/Source/Scenes/1_Main/1_Main/C_Settings/0_Settings/SettingsViewModel.swift +++ b/Source/Scenes/1_Main/1_Main/C_Settings/0_Settings/SettingsViewModel.swift @@ -162,12 +162,12 @@ private extension SettingsViewModel { let appName = bundle.name else { incorrectImplementation("Should be able to read name, version and build number") } - let networkDisplayName = DefaultUseCaseProvider.zilliqaAPIEndpoint.displayName + let networkDisplayName = network.displayName return "\(appName) v\(version) (\(build))\n\(L10n.Scene.Settings.Footer.network(networkDisplayName))" } } -private extension ZilliqaAPIEndpoint { +private extension Network { var displayName: String { switch self { case .mainnet: return "mainnet" diff --git a/Source/UseCases/Implementations/DefaultTransactionsUseCase.swift b/Source/UseCases/Implementations/DefaultTransactionsUseCase.swift index c0bdf54e..8e02a81c 100644 --- a/Source/UseCases/Implementations/DefaultTransactionsUseCase.swift +++ b/Source/UseCases/Implementations/DefaultTransactionsUseCase.swift @@ -65,7 +65,7 @@ extension DefaultTransactionsUseCase: TransactionsUseCase { balanceWasUpdated(at: Date()) } - func getBalance(for address: AddressChecksummedConvertible) -> Observable { + func getBalance(for address: LegacyAddress) -> Observable { return zilliqaService.getBalance(for: address) } diff --git a/Source/UseCases/Implementations/DefaultUseCaseProvider.swift b/Source/UseCases/Implementations/DefaultUseCaseProvider.swift index 5a6c7566..a101c4d4 100644 --- a/Source/UseCases/Implementations/DefaultUseCaseProvider.swift +++ b/Source/UseCases/Implementations/DefaultUseCaseProvider.swift @@ -33,12 +33,12 @@ extension KeyValueStore where KeyType == PreferencesKey { } } -final class DefaultUseCaseProvider { +let network: Network = .mainnet - static let zilliqaAPIEndpoint: ZilliqaAPIEndpoint = .mainnet +final class DefaultUseCaseProvider { static let shared = DefaultUseCaseProvider( - zilliqaService: DefaultZilliqaService(endpoint: zilliqaAPIEndpoint).rx, + zilliqaService: DefaultZilliqaService(network: network).rx, preferences: .default, securePersistence: KeyValueStore(KeychainSwift()) ) @@ -51,6 +51,7 @@ final class DefaultUseCaseProvider { self.zilliqaService = zilliqaService self.preferences = preferences self.securePersistence = securePersistence + } } diff --git a/Source/UseCases/TransactionsUseCase.swift b/Source/UseCases/TransactionsUseCase.swift index 4375b655..fe23dd8f 100644 --- a/Source/UseCases/TransactionsUseCase.swift +++ b/Source/UseCases/TransactionsUseCase.swift @@ -29,7 +29,7 @@ protocol TransactionsUseCase { var cachedBalance: ZilAmount? { get } func cacheBalance(_ balance: ZilAmount) - func getBalance(for address: AddressChecksummedConvertible) -> Observable + func getBalance(for address: LegacyAddress) -> Observable func deleteCachedBalance() var balanceUpdatedAt: Date? { get } func balanceWasUpdated(at date: Date) diff --git a/Source/Views/Delegates/TextFieldDelegate.swift b/Source/Views/Delegates/TextFieldDelegate.swift index 5a81d3f7..5695209f 100644 --- a/Source/Views/Delegates/TextFieldDelegate.swift +++ b/Source/Views/Delegates/TextFieldDelegate.swift @@ -26,30 +26,34 @@ import UIKit final class TextFieldDelegate: NSObject { private let maxLength: Int? - private var allowedCharacters: CharacterSet - init(allowedCharacters: CharacterSet, maxLength: Int? = nil) { - self.allowedCharacters = allowedCharacters + private var limitingCharacterSet: CharacterSet? + init(limitingCharacterSet: CharacterSet?, maxLength: Int? = nil) { + self.limitingCharacterSet = limitingCharacterSet self.maxLength = maxLength } } extension TextFieldDelegate { convenience init(type: FloatingLabelTextField.TypeOfInput = .text, maxLength: Int? = nil) { - self.init(allowedCharacters: type.characterSet, maxLength: maxLength) + self.init(limitingCharacterSet: type.limitingCharacterSet, maxLength: maxLength) } func setTypeOfInput( _ typeOfInput: FloatingLabelTextField.TypeOfInput) { - allowedCharacters = typeOfInput.characterSet + limitingCharacterSet = typeOfInput.limitingCharacterSet } } extension TextFieldDelegate: UITextFieldDelegate { func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { // Always allow erasing of digit - guard !string.isBackspace else { return true } + if string.isBackspace { return true } - // Dont allow pasting of non numbers - guard allowedCharacters.isSuperset(of: CharacterSet(charactersIn: string)) else { return false } + if let limitingCharacterSet = limitingCharacterSet { + if !limitingCharacterSet.isSuperset(of: CharacterSet(charactersIn: string)) { + // Dont allow pasting of non allowed chacracters + return false + } + } guard let maxLength = maxLength else { return true diff --git a/Source/Views/Subclasses/FloatingLabelTextField/FloatingLabelTextField+TypeOfInput.swift b/Source/Views/Subclasses/FloatingLabelTextField/FloatingLabelTextField+TypeOfInput.swift index 177ee1c3..1f4be68a 100644 --- a/Source/Views/Subclasses/FloatingLabelTextField/FloatingLabelTextField+TypeOfInput.swift +++ b/Source/Views/Subclasses/FloatingLabelTextField/FloatingLabelTextField+TypeOfInput.swift @@ -23,20 +23,24 @@ // import Foundation +import Zesame extension FloatingLabelTextField { enum TypeOfInput { - case number, hexadecimal, text + case number, hexadecimal, text, password, bech32, bech32OrHex } } extension FloatingLabelTextField.TypeOfInput { - var characterSet: CharacterSet { + var limitingCharacterSet: CharacterSet? { switch self { case .number: return .decimalDigits case .hexadecimal: return .hexadecimalDigits + case .bech32: return .bech32 + case .password: return nil case .text: return .alphanumerics + case .bech32OrHex: return .bech32OrHex } } }