diff --git a/.gitignore b/.gitignore index da0c5d9397..9ed5aa4cf6 100644 --- a/.gitignore +++ b/.gitignore @@ -85,6 +85,7 @@ Trust.zip # VIM *.swp *.swo +*~ # node node_modules diff --git a/Podfile b/Podfile index d83a287961..b18090a9d6 100644 --- a/Podfile +++ b/Podfile @@ -25,7 +25,7 @@ target 'Trust' do pod 'Crashlytics', '~> 3.10' pod 'Firebase/Core' pod 'Kingfisher', '~> 4.0' - pod 'TrustCore', '~> 0.0.6' + pod 'TrustCore', '~> 0.0.7' pod 'TrustKeystore', '~> 0.4.0' pod 'Branch' pod 'SAMKeychain' diff --git a/Podfile.lock b/Podfile.lock index d99b1c8f89..446f06c5e7 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -71,7 +71,7 @@ PODS: - StatefulViewController (3.0) - SwiftLint (0.25.0) - TrezorCrypto (0.0.5) - - TrustCore (0.0.6): + - TrustCore (0.0.7): - BigInt - TrezorCrypto - TrustKeystore (0.4.0): @@ -109,7 +109,7 @@ DEPENDENCIES: - SeedStackViewController - StatefulViewController - SwiftLint - - TrustCore (~> 0.0.6) + - TrustCore (~> 0.0.7) - TrustKeystore (~> 0.4.0) - TrustSDK (from `https://github.com/TrustWallet/TrustSDK-iOS`, branch `master`) - TrustWeb3Provider (from `https://github.com/TrustWallet/trust-web3-provider`, branch `master`) @@ -224,12 +224,12 @@ SPEC CHECKSUMS: StatefulViewController: 4803bf900d44de26074344998e10e041113b5931 SwiftLint: e14651157288e9e01d6e1a71db7014fb5744a8ea TrezorCrypto: ecef681446bf02af6248d3b5e394026d7e766e56 - TrustCore: 231439190d1941dc4e945c51c55c5effa8e7b9b4 + TrustCore: 688df9a241008cf9cfa3842ec8ef28777a8b7534 TrustKeystore: 1bd016c67de7314e84b79dba2c22ef64b86bb63e TrustSDK: fe6aac90d0ae5ca0be5b6ccd09f0008d1e223f1d TrustWeb3Provider: 50fa391bdf170feb43dd4419992931510a5751d8 URLNavigator: af5582fbbb3586c958be16835d799bfdb23a4793 -PODFILE CHECKSUM: 565e25f77aef23eca1fe772ccf54bb23e5ea553e +PODFILE CHECKSUM: 407574053cad2a6d49a5e6356743e399229e35b6 COCOAPODS: 1.5.0 diff --git a/Trust.xcodeproj/project.pbxproj b/Trust.xcodeproj/project.pbxproj index 956ec51d07..6a549f40a4 100644 --- a/Trust.xcodeproj/project.pbxproj +++ b/Trust.xcodeproj/project.pbxproj @@ -423,12 +423,16 @@ BB03A8712042B01300649DA0 /* BalanceStatusTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB03A8702042B01300649DA0 /* BalanceStatusTests.swift */; }; BB1CC266203BA4440042E56C /* SendMaxAmountTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1CC265203BA4440042E56C /* SendMaxAmountTest.swift */; }; BB1CC27A203D061B0042E56C /* TrustDocumentPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1CC279203D061B0042E56C /* TrustDocumentPickerViewController.swift */; }; + BB3395E9209C4F8100ACED2C /* ENSClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3395E8209C4F8100ACED2C /* ENSClient.swift */; }; BB3864A3208F1C8A00CBF773 /* testIsHexEncoded.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3864A2208F1C8A00CBF773 /* testIsHexEncoded.swift */; }; BB3864A4208F1C9C00CBF773 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29A0E1841F706B8C00BAAAED /* String.swift */; }; BB3864A5208F1D2600CBF773 /* Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2963B6C01F9AE0E4003063C1 /* Data.swift */; }; BB3B86BD204CE9730061FCBA /* URLNavigatorCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3B86BC204CE9730061FCBA /* URLNavigatorCoordinator.swift */; }; BB3B86BF204CECBC0061FCBA /* URLNavigable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3B86BE204CECBC0061FCBA /* URLNavigable.swift */; }; BB3B86C5204D2EF10061FCBA /* InCoordinator+Navigable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3B86C4204D2EF10061FCBA /* InCoordinator+Navigable.swift */; }; + BB3E2A0B20A03D22000F8B76 /* ENSStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3E2A0A20A03D22000F8B76 /* ENSStore.swift */; }; + BB3E2A0E20A04F4B000F8B76 /* ENSRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3E2A0D20A04F4B000F8B76 /* ENSRecord.swift */; }; + BB3E2A1020A12592000F8B76 /* ENSManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3E2A0F20A12592000F8B76 /* ENSManager.swift */; }; BB58B92D206F70E800A70A3C /* HistoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB58B92C206F70E800A70A3C /* HistoryStore.swift */; }; BB58B92F206F70FE00A70A3C /* History.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB58B92E206F70FE00A70A3C /* History.swift */; }; BB5D6A9E20232EE8000FC5AB /* CurrencyRate+Fee.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5D6A9D20232EE8000FC5AB /* CurrencyRate+Fee.swift */; }; @@ -901,10 +905,14 @@ BB03A8702042B01300649DA0 /* BalanceStatusTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BalanceStatusTests.swift; sourceTree = ""; }; BB1CC265203BA4440042E56C /* SendMaxAmountTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendMaxAmountTest.swift; sourceTree = ""; }; BB1CC279203D061B0042E56C /* TrustDocumentPickerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrustDocumentPickerViewController.swift; sourceTree = ""; }; + BB3395E8209C4F8100ACED2C /* ENSClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ENSClient.swift; sourceTree = ""; }; BB3864A2208F1C8A00CBF773 /* testIsHexEncoded.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = testIsHexEncoded.swift; sourceTree = ""; }; BB3B86BC204CE9730061FCBA /* URLNavigatorCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLNavigatorCoordinator.swift; sourceTree = ""; }; BB3B86BE204CECBC0061FCBA /* URLNavigable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLNavigable.swift; sourceTree = ""; }; BB3B86C4204D2EF10061FCBA /* InCoordinator+Navigable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "InCoordinator+Navigable.swift"; sourceTree = ""; }; + BB3E2A0A20A03D22000F8B76 /* ENSStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ENSStore.swift; sourceTree = ""; }; + BB3E2A0D20A04F4B000F8B76 /* ENSRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ENSRecord.swift; sourceTree = ""; }; + BB3E2A0F20A12592000F8B76 /* ENSManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ENSManager.swift; sourceTree = ""; }; BB58B92C206F70E800A70A3C /* HistoryStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryStore.swift; sourceTree = ""; }; BB58B92E206F70FE00A70A3C /* History.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = History.swift; sourceTree = ""; }; BB5D6A9D20232EE8000FC5AB /* CurrencyRate+Fee.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CurrencyRate+Fee.swift"; sourceTree = ""; }; @@ -1171,6 +1179,7 @@ 2923D9B41FDA4E07000CF3F8 /* PasswordGenerator.swift */, 61C359DF2002AA590097B04D /* TransactionSigning.swift */, 29F1C862200375D2003780D8 /* Wallet.swift */, + BB3E2A0C20A04F2C000F8B76 /* ENS */, ); path = EtherClient; sourceTree = ""; @@ -2433,6 +2442,17 @@ path = Extensions; sourceTree = ""; }; + BB3E2A0C20A04F2C000F8B76 /* ENS */ = { + isa = PBXGroup; + children = ( + BB3395E8209C4F8100ACED2C /* ENSClient.swift */, + BB3E2A0A20A03D22000F8B76 /* ENSStore.swift */, + BB3E2A0D20A04F4B000F8B76 /* ENSRecord.swift */, + BB3E2A0F20A12592000F8B76 /* ENSManager.swift */, + ); + path = ENS; + sourceTree = ""; + }; BB767E2C205E102700263658 /* Utils */ = { isa = PBXGroup; children = ( @@ -2874,6 +2894,7 @@ A2E43B4E20802879001FAD3D /* UINavigationController.swift in Sources */, 2963B6B11F9891F5003063C1 /* UIButton.swift in Sources */, 29F114F21FA7966300114A29 /* PrivateKeyRule.swift in Sources */, + BB3E2A0E20A04F4B000F8B76 /* ENSRecord.swift in Sources */, 77E81D962036883B00534C99 /* NotificationsViewModel.swift in Sources */, 7778713E2086F93700CF7303 /* Colors.swift in Sources */, 296106C41F7640C50006164B /* TokenViewCellViewModel.swift in Sources */, @@ -2898,6 +2919,7 @@ BB767E2E205E10FD00263658 /* Debounce.swift in Sources */, 77872D232023F43B0032D687 /* TransactionsTracker.swift in Sources */, 776C1147205CF6DF00449539 /* TokenHeaderView.swift in Sources */, + BB3E2A0B20A03D22000F8B76 /* ENSStore.swift in Sources */, 29FA00CE201CA64E002F7DC5 /* DappCommand.swift in Sources */, 29FF12F61F74799D00AFD326 /* NSAttributedString.swift in Sources */, 290B2B651F91A4880053C83E /* TransactionsFooterView.swift in Sources */, @@ -3157,6 +3179,8 @@ 29BB94951F6FC54C009B09CC /* EthereumUnit.swift in Sources */, 29C70C712016C7780072E454 /* SentTransaction.swift in Sources */, 29E9CFD21FE737FE00017744 /* TrustRealmConfiguration.swift in Sources */, + BB3395E9209C4F8100ACED2C /* ENSClient.swift in Sources */, + BB3E2A1020A12592000F8B76 /* ENSManager.swift in Sources */, 2959961C1FAE3EDF00DB66A8 /* TrustClient.swift in Sources */, 29AD8A0C1F93FBBF008E10E7 /* Subscribable.swift in Sources */, 777871382085D7A600CF7303 /* BranchEvent.swift in Sources */, diff --git a/Trust/Accounts/Coordinators/AccountsCoordinator.swift b/Trust/Accounts/Coordinators/AccountsCoordinator.swift index d2910cda0e..ad02b0c7cb 100644 --- a/Trust/Accounts/Coordinators/AccountsCoordinator.swift +++ b/Trust/Accounts/Coordinators/AccountsCoordinator.swift @@ -18,10 +18,11 @@ class AccountsCoordinator: Coordinator { let keystore: Keystore let session: WalletSession let balanceCoordinator: TokensBalanceService + let ensManager: ENSManager var coordinators: [Coordinator] = [] lazy var accountsViewController: AccountsViewController = { - let controller = AccountsViewController(keystore: keystore, balanceCoordinator: balanceCoordinator) + let controller = AccountsViewController(keystore: keystore, balanceCoordinator: balanceCoordinator, ensManager: ensManager) controller.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(add)) controller.delegate = self return controller @@ -33,13 +34,15 @@ class AccountsCoordinator: Coordinator { navigationController: NavigationController, keystore: Keystore, session: WalletSession, - balanceCoordinator: TokensBalanceService + balanceCoordinator: TokensBalanceService, + ensManager: ENSManager ) { self.navigationController = navigationController self.navigationController.modalPresentationStyle = .formSheet self.keystore = keystore self.session = session self.balanceCoordinator = balanceCoordinator + self.ensManager = ensManager } func start() { diff --git a/Trust/Accounts/ViewModels/AccountViewModel.swift b/Trust/Accounts/ViewModels/AccountViewModel.swift index 4096d73067..699daa97ff 100644 --- a/Trust/Accounts/ViewModels/AccountViewModel.swift +++ b/Trust/Accounts/ViewModels/AccountViewModel.swift @@ -11,17 +11,20 @@ struct AccountViewModel { let current: Wallet? let walletBalance: Balance? let server: RPCServer + let ensName: String init( server: RPCServer, wallet: Wallet, current: Wallet?, - walletBalance: Balance? + walletBalance: Balance?, + ensName: String = "" ) { self.server = server self.wallet = wallet self.current = current self.walletBalance = walletBalance + self.ensName = ensName } var isWatch: Bool { @@ -34,7 +37,11 @@ struct AccountViewModel { } var title: String { - return wallet.address.description + let address = wallet.address.description + if ensName.isEmpty { + return address + } + return String(format: "%@ (%@...%@)", ensName, String(address.prefix(6)), String(address.suffix(4))) } var isActive: Bool { diff --git a/Trust/Accounts/ViewModels/AccountsViewController.swift b/Trust/Accounts/ViewModels/AccountsViewController.swift index 115d76836b..c29758bfb7 100644 --- a/Trust/Accounts/ViewModels/AccountsViewController.swift +++ b/Trust/Accounts/ViewModels/AccountsViewController.swift @@ -2,6 +2,7 @@ import TrustCore import UIKit +import PromiseKit protocol AccountsViewControllerDelegate: class { func didSelectAccount(account: Wallet, in viewController: AccountsViewController) @@ -10,6 +11,7 @@ protocol AccountsViewControllerDelegate: class { } class AccountsViewController: UITableViewController { + let ensManager: ENSManager weak var delegate: AccountsViewControllerDelegate? var headerTitle: String? var viewModel: AccountsViewModel { @@ -27,16 +29,19 @@ class AccountsViewController: UITableViewController { } } private var balances: [Address: Balance?] = [:] + private var addrNames: [Address: String] = [:] private let keystore: Keystore private let balanceCoordinator: TokensBalanceService private let config = Config() init( keystore: Keystore, - balanceCoordinator: TokensBalanceService + balanceCoordinator: TokensBalanceService, + ensManager: ENSManager ) { self.keystore = keystore self.balanceCoordinator = balanceCoordinator + self.ensManager = ensManager super.init(style: .grouped) fetch() } @@ -52,6 +57,7 @@ class AccountsViewController: UITableViewController { super.viewWillAppear(animated) fetch() refreshWalletBalances() + refreshENSNames() } func fetch() { @@ -153,10 +159,24 @@ class AccountsViewController: UITableViewController { } } + private func refreshENSNames() { + let addresses = wallets.compactMap { $0.address } + let promises = addresses.map { ensManager.lookup(address: $0) } + _ = when(fulfilled: promises).done { [weak self] names in + for (index, name) in names.enumerated() { + self?.addrNames[addresses[index]] = name + } + self?.tableView.reloadData() + }.catch { error in + print(error) + } + } + private func getAccountViewModels(for path: IndexPath) -> AccountViewModel { let account = self.wallet(for: path)! // Avoid force unwrap let balance = self.balances[account.address].flatMap { $0 } - let model = AccountViewModel(server: config.server, wallet: account, current: EtherKeystore.current, walletBalance: balance) + let ensName = self.addrNames[account.address] ?? "" + let model = AccountViewModel(server: config.server, wallet: account, current: EtherKeystore.current, walletBalance: balance, ensName: ensName) return model } diff --git a/Trust/Accounts/Views/AccountViewCell.swift b/Trust/Accounts/Views/AccountViewCell.swift index b167f53339..1d88acaaec 100644 --- a/Trust/Accounts/Views/AccountViewCell.swift +++ b/Trust/Accounts/Views/AccountViewCell.swift @@ -12,8 +12,8 @@ class AccountViewCell: UITableViewCell { @IBOutlet weak var activeView: UIView! @IBOutlet weak var glassesImageView: UIImageView! @IBOutlet weak var walletTypeImageView: UIImageView! - @IBOutlet weak var addressLable: UILabel! - @IBOutlet weak var balanceLable: UILabel! + @IBOutlet weak var balanceLabel: UILabel! + @IBOutlet weak var addressLabel: UILabel! @IBOutlet weak var identiconImageView: UIImageView! weak var delegate: AccountViewCellDelegate? var viewModel: AccountViewModel? { @@ -21,10 +21,10 @@ class AccountViewCell: UITableViewCell { guard let model = viewModel else { return } - balanceLable.text = model.balanceText + balanceLabel.text = model.balanceText glassesImageView.isHidden = !model.isWatch activeView.isHidden = !model.isActive - addressLable.text = model.title + addressLabel.text = model.title infoButton.tintColor = Colors.lightBlue identiconImageView.image = model.identicon } diff --git a/Trust/Accounts/Views/AccountViewCell.xib b/Trust/Accounts/Views/AccountViewCell.xib index dc3da0977b..534203c369 100644 --- a/Trust/Accounts/Views/AccountViewCell.xib +++ b/Trust/Accounts/Views/AccountViewCell.xib @@ -1,11 +1,11 @@ - + - + @@ -23,8 +23,9 @@ - + + @@ -33,17 +34,17 @@ - - + + - - + @@ -111,8 +112,8 @@ - - + + diff --git a/Trust/EtherClient/ENS/ENSClient.swift b/Trust/EtherClient/ENS/ENSClient.swift new file mode 100644 index 0000000000..e98a6ab965 --- /dev/null +++ b/Trust/EtherClient/ENS/ENSClient.swift @@ -0,0 +1,110 @@ +// Copyright SIX DAY LLC. All rights reserved. + +import Foundation +import TrustCore +import JSONRPCKit +import PromiseKit +import APIKit + +enum ENSError: LocalizedError { + case decodeError +} + +// move to TrustCore later +final class PublicResolverEncoder { + public static func encodeAddr(node: Data) -> Data { + let function = Function(name: "addr", parameters: [.bytes(32)]) + let encoder = ABIEncoder() + try! encoder.encode(function: function, arguments: [node]) + return encoder.data + } +} + +typealias ENSResolveResult = (resolver: Address, address: Address) + +struct ENSClient { + + static let ensContrct = Address(string: "0x314159265dd8dbb310642f98f50c066173c1259b")! + static let publicResolverContract = Address(string: "0x5fbb459c49bb06083c33109fa4f14810ec2cf358")! + static let reverseResolverContract = Address(string: "0x5fbb459c49bb06083c33109fa4f14810ec2cf358")! + static let reverseSuffix = "addr.reverse" + + func resolve(name: String) -> Promise { + return firstly { + return self.resolverOf(name: name) + }.then { resolver -> Promise in + if resolver == Address.zero { + return Promise { $0.resolve((resolver: resolver, address: resolver), nil) } + } + let encoded = PublicResolverEncoder.encodeAddr(node: namehash(name)) + let request = EtherServiceRequest( + batch: BatchFactory().create(CallRequest(to: resolver.description, data: encoded.hexEncoded)) + ) + return self.sendAddr(request: request).compactMap { address -> ENSResolveResult in + return (resolver: resolver, address: address) + } + } + } + + func resolverOf(name: String) -> Promise
{ + let node = namehash(name) + let encoded = ENSEncoder.encodeResolver(node: node) + let request = EtherServiceRequest( + batch: BatchFactory().create(CallRequest(to: ENSClient.ensContrct.description, data: encoded.hexEncoded)) + ) + return self.sendAddr(request: request) + } + + func ownerOf(name: String) -> Promise
{ + let node = namehash(name) + let encoded = ENSEncoder.encodeOwner(node: node) + let request = EtherServiceRequest( + batch: BatchFactory().create(CallRequest(to: ENSClient.ensContrct.description, data: encoded.hexEncoded)) + ) + return self.sendAddr(request: request) + } + + private func sendAddr(request: EtherServiceRequest>) -> Promise
{ + return Promise { seal in + Session.send(request) { result in + switch result { + case .success(let response): + let data = Data(hex: response) + guard data.count == 32 else { + return seal.reject(ENSError.decodeError) + } + //take the last 20 bytes for Address + let sub = data.suffix(20) + seal.fulfill(Address(data: sub)) + case .failure(let error): + seal.reject(error) + } + } + } + } + + func lookup(address: Address) -> Promise { + let addr = [address.data.hex, ENSClient.reverseSuffix].joined(separator: ".") + let node = namehash(addr) + let encoded = ReverseResolverEncoder.encodeName(node) + let request = EtherServiceRequest( + batch: BatchFactory().create(CallRequest(to: ENSClient.reverseResolverContract.description, data: encoded.hexEncoded)) + ) + return Promise { seal in + Session.send(request) { result in + switch result { + case .success(let response): + let data = Data(hex: response) + let decoder = ABIDecoder(data: data) + let decoded = try? decoder.decodeTuple(types: [.string]) + guard let string = decoded?.first?.nativeValue as? String else { + return seal.reject(ENSError.decodeError) + } + seal.fulfill(string) + case .failure(let error): + seal.reject(error) + } + } + } + } +} diff --git a/Trust/EtherClient/ENS/ENSManager.swift b/Trust/EtherClient/ENS/ENSManager.swift new file mode 100644 index 0000000000..b0065adc94 --- /dev/null +++ b/Trust/EtherClient/ENS/ENSManager.swift @@ -0,0 +1,45 @@ +// Copyright SIX DAY LLC. All rights reserved. + +import Foundation +import TrustCore +import RealmSwift +import PromiseKit + +struct ENSManager { + + var store: ENSStore + let localInterval: Double = 24 * 60 * 60 // 1 day + let client = ENSClient() + + init(realm: Realm) { + self.store = ENSStore(realm: realm) + } + + func resolve(name: String, ignoreCache: Bool = false) -> Promise
{ + let now = Date() + let filtered = store.records.filter("name == %@", name) + if ignoreCache == false, let record = filtered.first, now.timeIntervalSince(record.updatedAt) <= localInterval { + return Promise { $0.resolve(Address(string: record.owner), nil) } + } + return client.resolve(name: name).map { result -> Address in + if result.address != Address.zero { + self.store.add(record: ENSRecord(name: name, address: result.address.description, resolver: result.resolver.description)) + } + return result.address + } + } + + func lookup(address: Address, ignoreCache: Bool = false) -> Promise { + let now = Date() + let filtered = store.records.filter("address == %@", address.description) + if ignoreCache == false, let record = filtered.first, now.timeIntervalSince(record.updatedAt) <= localInterval { + return Promise { $0.resolve(record.name, nil) } + } + return client.lookup(address: address).map { name -> String in + if !name.isEmpty { + self.store.add(record: ENSRecord(name: name, address: address.description, isReverse: true)) + } + return name + } + } +} diff --git a/Trust/EtherClient/ENS/ENSRecord.swift b/Trust/EtherClient/ENS/ENSRecord.swift new file mode 100644 index 0000000000..5cc68c80a1 --- /dev/null +++ b/Trust/EtherClient/ENS/ENSRecord.swift @@ -0,0 +1,30 @@ +// Copyright SIX DAY LLC. All rights reserved. + +import Foundation +import RealmSwift + +class ENSRecord: Object { + + @objc dynamic var name: String = "" + @objc dynamic var owner: String = "" + @objc dynamic var resolver: String = "" + @objc dynamic var address: String = "" + @objc dynamic var ttl: Int = 0 + + @objc dynamic var updatedAt: Date = Date() + @objc dynamic var isReverse: Bool = false + + convenience init(name: String, address: String, owner: String = "", resolver: String = "", isReverse: Bool = false, updatedAt: Date = Date()) { + self.init() + self.name = name + self.owner = owner + self.address = address + self.resolver = resolver + self.updatedAt = updatedAt + self.isReverse = isReverse + } + + override class func primaryKey() -> String? { + return "name" + } +} diff --git a/Trust/EtherClient/ENS/ENSStore.swift b/Trust/EtherClient/ENS/ENSStore.swift new file mode 100644 index 0000000000..e8034bb1de --- /dev/null +++ b/Trust/EtherClient/ENS/ENSStore.swift @@ -0,0 +1,28 @@ +// Copyright SIX DAY LLC. All rights reserved. + +import Foundation +import RealmSwift + +struct ENSStore { + var records: Results { + return realm.objects(ENSRecord.self) + } + + let realm: Realm + + init(realm: Realm) { + self.realm = realm + } + + func add(record: ENSRecord) { + try? realm.write { + realm.add([record], update: true) + } + } + + func removeAll() { + try? realm.write { + realm.delete(records) + } + } +} diff --git a/Trust/InCoordinator.swift b/Trust/InCoordinator.swift index 861bd90d57..f72f5f80e7 100644 --- a/Trust/InCoordinator.swift +++ b/Trust/InCoordinator.swift @@ -136,7 +136,8 @@ class InCoordinator: Coordinator { session: session, storage: transactionsStorage, balanceCoordinator: balanceCoordinator, - sharedRealm: sharedRealm + sharedRealm: sharedRealm, + ensManager: ENSManager(realm: realm) ) settingsCoordinator.rootViewController.tabBarItem = viewModel.settingsBarItem settingsCoordinator.delegate = self diff --git a/Trust/Settings/Coordinators/SettingsCoordinator.swift b/Trust/Settings/Coordinators/SettingsCoordinator.swift index fab8368661..670f0ce34c 100644 --- a/Trust/Settings/Coordinators/SettingsCoordinator.swift +++ b/Trust/Settings/Coordinators/SettingsCoordinator.swift @@ -20,6 +20,7 @@ class SettingsCoordinator: Coordinator { let session: WalletSession let storage: TransactionsStorage let balanceCoordinator: TokensBalanceService + let ensManager: ENSManager weak var delegate: SettingsCoordinatorDelegate? let pushNotificationsRegistrar = PushNotificationsRegistrar() var coordinators: [Coordinator] = [] @@ -29,7 +30,8 @@ class SettingsCoordinator: Coordinator { navigationController: navigationController, keystore: keystore, session: session, - balanceCoordinator: balanceCoordinator + balanceCoordinator: balanceCoordinator, + ensManager: ensManager ) coordinator.delegate = self return coordinator @@ -57,7 +59,8 @@ class SettingsCoordinator: Coordinator { session: WalletSession, storage: TransactionsStorage, balanceCoordinator: TokensBalanceService, - sharedRealm: Realm + sharedRealm: Realm, + ensManager: ENSManager ) { self.navigationController = navigationController self.navigationController.modalPresentationStyle = .formSheet @@ -66,6 +69,7 @@ class SettingsCoordinator: Coordinator { self.storage = storage self.balanceCoordinator = balanceCoordinator self.sharedRealm = sharedRealm + self.ensManager = ensManager addCoordinator(accountsCoordinator) } diff --git a/TrustTests/Settings/Coordinators/SettingsCoordinatorTests.swift b/TrustTests/Settings/Coordinators/SettingsCoordinatorTests.swift index a562852853..220c366018 100644 --- a/TrustTests/Settings/Coordinators/SettingsCoordinatorTests.swift +++ b/TrustTests/Settings/Coordinators/SettingsCoordinatorTests.swift @@ -13,7 +13,8 @@ class SettingsCoordinatorTests: XCTestCase { session: .make(), storage: storage, balanceCoordinator: FakeGetBalanceCoordinator(), - sharedRealm: .make() + sharedRealm: .make(), + ensManager: ENSManager(realm: .make()) ) storage.add([.make()]) storage.updateTransactionSection() @@ -24,7 +25,8 @@ class SettingsCoordinatorTests: XCTestCase { navigationController: FakeNavigationController(), keystore: FakeEtherKeystore(), session: .make(), - balanceCoordinator: FakeGetBalanceCoordinator() + balanceCoordinator: FakeGetBalanceCoordinator(), + ensManager: ENSManager(realm: .make()) ) coordinator.didDeleteAccount(account: .make(), in: accountCoordinator)